1 /*****************************************************************************
\r
2 * main.cpp: ActiveX control for VLC
\r
3 *****************************************************************************
\r
4 * Copyright (C) 2005 VideoLAN
\r
6 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
\r
8 * This program is free software; you can redistribute it and/or modify
\r
9 * it under the terms of the GNU General Public License as published by
\r
10 * the Free Software Foundation; either version 2 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU General Public License
\r
19 * along with this program; if not, write to the Free Software
\r
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
\r
21 *****************************************************************************/
\r
26 #include <windows.h>
\r
27 #include <shlwapi.h>
\r
29 using namespace std;
\r
31 #define COMDLLPATH "axvlc.dll"
\r
32 #define THREADING_MODEL "Both"
\r
33 #define COMPANY_STR "VideoLAN"
\r
34 #define PROGRAM_STR "VLCPlugin"
\r
35 #define VERSION_MAJOR_STR "1"
\r
36 #define VERSION_MINOR_STR "0"
\r
37 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
\r
39 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
\r
40 #define VERS_PROGID_STR COMPANY_STR"."PROGRAM_STR"."VERSION_MAJOR_STR
\r
41 #define VERSION_STR VERSION_MAJOR_STR"."VERSION_MINOR_STR
\r
43 #define GUID_STRLEN 39
\r
46 ** MingW headers do not declare those
\r
48 extern const CATID CATID_SafeForInitializing;
\r
49 extern const CATID CATID_SafeForScripting;
\r
51 static LONG i_class_ref= 0;
\r
52 static HINSTANCE h_instance= 0;
\r
54 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
\r
56 HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
\r
60 if( CLSID_VLCPlugin == rclsid )
\r
62 VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);
\r
63 hr = plugin->QueryInterface(riid, ppv);
\r
69 STDAPI DllCanUnloadNow(VOID)
\r
71 return (0 == i_class_ref) ? S_OK: S_FALSE;
\r
74 static LPCTSTR TStrFromGUID(REFGUID clsid) {
\r
77 if( FAILED(StringFromIID(clsid, &oleStr)) )
\r
80 //check whether TCHAR and OLECHAR are both either ANSI or UNICODE
\r
81 if( sizeof(TCHAR) == sizeof(OLECHAR) )
\r
82 return (LPCTSTR)oleStr;
\r
84 LPTSTR pct_CLSID = NULL;
\r
86 size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);
\r
89 pct_CLSID = (char *)CoTaskMemAlloc(len);
\r
90 WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);
\r
93 size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);
\r
96 clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));
\r
97 WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len);
\r
100 CoTaskMemFree(oleStr);
\r
104 static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
\r
107 if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
\r
108 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
\r
115 STDAPI DllUnregisterServer(VOID)
\r
117 // unregister type lib from the registry
\r
118 UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
\r
120 // remove component categories we supports
\r
122 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
\r
123 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
\r
124 CATID implCategories[] = {
\r
126 CATID_PersistsToPropertyBag,
\r
127 CATID_SafeForInitializing,
\r
128 CATID_SafeForScripting,
\r
131 pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
\r
132 sizeof(implCategories)/sizeof(CATID), implCategories);
\r
136 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
\r
137 SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
\r
139 LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
\r
141 if( NULL == psz_CLSID )
\r
142 return E_OUTOFMEMORY;
\r
145 if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
\r
147 SHDeleteKey(hClsIDKey, psz_CLSID);
\r
148 RegCloseKey(hClsIDKey);
\r
154 STDAPI DllRegisterServer(VOID)
\r
156 DllUnregisterServer();
\r
158 LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
\r
160 if( NULL == psz_CLSID )
\r
161 return E_OUTOFMEMORY;
\r
165 if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
\r
168 HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);
\r
169 if( NULL != hClassKey )
\r
173 // default key value
\r
174 RegSetValueEx(hClassKey, NULL, 0, REG_SZ,
\r
175 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
\r
177 // Control key value
\r
178 hSubKey = keyCreate(hClassKey, TEXT("Control"));
\r
179 RegCloseKey(hSubKey);
\r
181 // InprocServer32 key value
\r
182 hSubKey = keyCreate(hClassKey, TEXT("InprocServer32"));
\r
183 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
184 (const BYTE*)COMDLLPATH, sizeof(COMDLLPATH));
\r
185 RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,
\r
186 (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));
\r
187 RegCloseKey(hSubKey);
\r
189 // MiscStatus key value
\r
190 hSubKey = keyCreate(hClassKey, TEXT("MiscStatus\\1"));
\r
191 RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (const BYTE*)"131473", sizeof("131473"));
\r
192 RegCloseKey(hSubKey);
\r
194 // Programmable key value
\r
195 hSubKey = keyCreate(hClassKey, TEXT("Programmable"));
\r
196 RegCloseKey(hSubKey);
\r
198 // ProgID key value
\r
199 hSubKey = keyCreate(hClassKey, TEXT("ProgID"));
\r
200 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
201 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
\r
202 RegCloseKey(hSubKey);
\r
204 // VersionIndependentProgID key value
\r
205 hSubKey = keyCreate(hClassKey, TEXT("VersionIndependentProgID"));
\r
206 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
207 (const BYTE*)PROGID_STR, sizeof(PROGID_STR));
\r
208 RegCloseKey(hSubKey);
\r
210 // Version key value
\r
211 hSubKey = keyCreate(hClassKey, TEXT("Version"));
\r
212 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
213 (const BYTE*)VERSION_STR, sizeof(VERSION_STR));
\r
214 RegCloseKey(hSubKey);
\r
216 // TypeLib key value
\r
217 LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);
\r
218 if( NULL != psz_LIBID )
\r
220 hSubKey = keyCreate(hClassKey, TEXT("TypeLib"));
\r
221 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
222 (const BYTE*)psz_LIBID, sizeof(TCHAR)*GUID_STRLEN);
\r
223 RegCloseKey(hSubKey);
\r
225 RegCloseKey(hClassKey);
\r
227 RegCloseKey(hBaseKey);
\r
229 hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
\r
230 if( NULL != hBaseKey )
\r
232 // default key value
\r
233 RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
\r
234 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
\r
236 HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
\r
237 if( NULL != hSubKey )
\r
239 // default key value
\r
240 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
241 (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
\r
243 RegCloseKey(hSubKey);
\r
245 hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));
\r
246 if( NULL != hSubKey )
\r
248 // default key value
\r
249 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
250 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
\r
252 RegCloseKey(hSubKey);
\r
254 RegCloseKey(hBaseKey);
\r
257 hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
\r
258 if( NULL != hBaseKey )
\r
260 // default key value
\r
261 RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
\r
262 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
\r
264 HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
\r
265 if( NULL != hSubKey )
\r
267 // default key value
\r
268 RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
\r
269 (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
\r
271 RegCloseKey(hSubKey);
\r
273 RegCloseKey(hBaseKey);
\r
276 // indicate which component categories we support
\r
278 if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
\r
279 NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
\r
280 CATID implCategories[] = {
\r
282 CATID_PersistsToPropertyBag,
\r
283 CATID_SafeForInitializing,
\r
284 CATID_SafeForScripting,
\r
287 pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
\r
288 sizeof(implCategories)/sizeof(CATID), implCategories);
\r
292 // register type lib into the registry
\r
294 if( SUCCEEDED(LoadTypeLibEx(OLESTR("")COMDLLPATH, REGKIND_REGISTER, &typeLib)) )
\r
295 typeLib->Release();
\r
300 #ifdef BUILD_LOCALSERVER
\r
303 ** easier to debug an application than a DLL on cygwin GDB :)
\r
305 #include <stream.h>
\r
307 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
\r
311 if( FAILED(OleInitialize(NULL)) )
\r
313 cerr << "cannot initialize OLE" << endl;
\r
317 IUnknown *classProc = NULL;
\r
319 if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
\r
322 DWORD dwRegisterClassObject;
\r
324 if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
\r
325 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
\r
328 DWORD dwRegisterActiveObject;
\r
330 if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
\r
331 ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
\r
334 classProc->Release();
\r
337 * Polling messages from event queue
\r
339 while( S_FALSE == DllCanUnloadNow() )
\r
341 while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
\r
343 if( msg.message == WM_QUIT )
\r
344 break; // Leave the PeekMessage while() loop
\r
346 /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
\r
349 TranslateMessage(&msg);
\r
350 DispatchMessage(&msg);
\r
353 if(msg.message == WM_QUIT)
\r
354 break; // Leave the for() loop
\r
359 if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
\r
360 CoRevokeClassObject(dwRegisterClassObject);
\r
362 // Reached on WM_QUIT message
\r
364 return ((int) msg.wParam);
\r
369 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
\r
371 switch( fdwReason )
\r
373 case DLL_PROCESS_ATTACH:
\r
374 h_instance = (HINSTANCE)hModule;
\r