]> git.sesse.net Git - vlc/blob - activex/main.cpp
prepare release. We still need to update the Changelog
[vlc] / activex / main.cpp
1 /*****************************************************************************
2  * main.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 VideoLAN
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23 #include "plugin.h"
24
25 #include <comcat.h>
26 #include <windows.h>
27 #include <shlwapi.h>
28
29 using namespace std;
30
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"
36
37 #define THREADING_MODEL "Apartment"
38 #define MISC_STATUS     "131473"
39
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
43
44 #define GUID_STRLEN 39
45
46 /*
47 ** MingW headers do not declare those
48 */
49 extern const CATID CATID_SafeForInitializing;
50 extern const CATID CATID_SafeForScripting;
51
52 static LONG i_class_ref= 0;
53 static HINSTANCE h_instance= 0;
54
55 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
56 {
57     HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
58
59     *ppv = NULL;
60
61     if( CLSID_VLCPlugin == rclsid )
62     {
63         VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);
64         hr = plugin->QueryInterface(riid, ppv);
65         plugin->Release();
66     }
67     return hr;
68 };
69
70 STDAPI DllCanUnloadNow(VOID)
71 {
72     return (0 == i_class_ref) ? S_OK: S_FALSE;
73 };
74
75 static LPCTSTR TStrFromGUID(REFGUID clsid)
76 {
77     LPOLESTR oleStr;
78
79     if( FAILED(StringFromIID(clsid, &oleStr)) )
80         return NULL;
81
82     //check whether TCHAR and OLECHAR are both either ANSI or UNICODE
83     if( sizeof(TCHAR) == sizeof(OLECHAR) )
84         return (LPCTSTR)oleStr;
85
86     LPTSTR pct_CLSID = NULL;
87 #ifndef OLE2ANSI
88     size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);
89     if( len > 0 )
90     {
91         pct_CLSID = (char *)CoTaskMemAlloc(len);
92         WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);
93     }
94 #else
95     size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);
96     if( len > 0 )
97     {
98         clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));
99         WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len);
100     }
101 #endif
102     CoTaskMemFree(oleStr);
103     return pct_CLSID;
104 };
105
106 static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
107 {
108     HKEY childKey;
109     if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
110                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
111     {
112         return childKey;
113     }
114     return NULL;
115 };
116
117 STDAPI DllUnregisterServer(VOID)
118 {
119     // unregister type lib from the registry
120     UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
121
122     // remove component categories we supports
123     ICatRegister *pcr;
124     if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
125             NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
126         CATID implCategories[] = {
127             CATID_Control,
128             CATID_PersistsToPropertyBag,
129             CATID_SafeForInitializing,
130             CATID_SafeForScripting,
131         };
132
133         pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
134                 sizeof(implCategories)/sizeof(CATID), implCategories);
135         pcr->Release();
136     }
137
138     SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
139     SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
140
141     LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
142
143     if( NULL == psz_CLSID )
144         return E_OUTOFMEMORY;
145
146     HKEY hClsIDKey;
147     if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
148     {
149         SHDeleteKey(hClsIDKey, psz_CLSID);
150         RegCloseKey(hClsIDKey);
151     }
152     CoTaskMemFree((void *)psz_CLSID);
153
154     return S_OK;
155 };
156
157 STDAPI DllRegisterServer(VOID)
158 {
159     DllUnregisterServer();
160
161     char DllPath[MAX_PATH];
162     DWORD DllPathLen= GetModuleFileName(h_instance, DllPath, sizeof(DllPath)) ;
163         if( 0 == DllPathLen )
164         return E_UNEXPECTED;
165
166     LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
167
168     if( NULL == psz_CLSID )
169         return E_OUTOFMEMORY;
170
171     HKEY hBaseKey;
172
173     if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
174         return SELFREG_E_CLASS;
175
176     HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);
177     if( NULL != hClassKey )
178     {
179         HKEY hSubKey;
180
181         // default key value
182         RegSetValueEx(hClassKey, NULL, 0, REG_SZ,
183                 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
184
185         // Control key value
186         hSubKey = keyCreate(hClassKey, TEXT("Control"));
187         RegCloseKey(hSubKey);
188
189 #ifdef BUILD_LOCALSERVER
190         // LocalServer32 key value
191         hSubKey = keyCreate(hClassKey, TEXT("LocalServer32"));
192         RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
193                 (const BYTE*)DllPath, DllPathLen);
194         RegCloseKey(hSubKey);
195 #else
196         // InprocServer32 key value
197         hSubKey = keyCreate(hClassKey, TEXT("InprocServer32"));
198         RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
199                 (const BYTE*)DllPath, DllPathLen);
200         RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,
201                 (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));
202         RegCloseKey(hSubKey);
203 #endif
204
205         // MiscStatus key value
206         hSubKey = keyCreate(hClassKey, TEXT("MiscStatus\\1"));
207         RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (const BYTE*)MISC_STATUS, sizeof(MISC_STATUS));
208         RegCloseKey(hSubKey);
209
210         // Programmable key value
211         hSubKey = keyCreate(hClassKey, TEXT("Programmable"));
212         RegCloseKey(hSubKey);
213
214         // ProgID key value
215         hSubKey = keyCreate(hClassKey, TEXT("ProgID"));
216         RegSetValueEx(hSubKey, NULL, 0, REG_SZ, 
217                 (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
218         RegCloseKey(hSubKey);
219
220         // VersionIndependentProgID key value
221         hSubKey = keyCreate(hClassKey, TEXT("VersionIndependentProgID"));
222         RegSetValueEx(hSubKey, NULL, 0, REG_SZ, 
223                 (const BYTE*)PROGID_STR, sizeof(PROGID_STR));
224         RegCloseKey(hSubKey);
225
226         // Version key value
227         hSubKey = keyCreate(hClassKey, TEXT("Version"));
228         RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
229                 (const BYTE*)VERSION_STR, sizeof(VERSION_STR));
230         RegCloseKey(hSubKey);
231
232         // TypeLib key value
233         LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);
234         if( NULL != psz_LIBID )
235         {
236             hSubKey = keyCreate(hClassKey, TEXT("TypeLib"));
237             RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
238                     (const BYTE*)psz_LIBID, sizeof(TCHAR)*GUID_STRLEN);
239             RegCloseKey(hSubKey);
240         }
241         RegCloseKey(hClassKey);
242     }
243     RegCloseKey(hBaseKey);
244
245     hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
246     if( NULL != hBaseKey )
247     {
248         // default key value
249         RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
250                 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
251
252         HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
253         if( NULL != hSubKey )
254         {
255             // default key value
256             RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
257                     (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
258
259             RegCloseKey(hSubKey);
260         }
261         hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));
262         if( NULL != hSubKey )
263         {
264             // default key value
265             RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
266                     (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
267
268             RegCloseKey(hSubKey);
269         }
270         RegCloseKey(hBaseKey);
271     }
272
273     hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
274     if( NULL != hBaseKey )
275     {
276         // default key value
277         RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
278                 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
279
280         HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
281         if( NULL != hSubKey )
282         {
283             // default key value
284             RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
285                     (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
286
287             RegCloseKey(hSubKey);
288         }
289         RegCloseKey(hBaseKey);
290     }
291
292     // indicate which component categories we support
293     ICatRegister *pcr;
294     if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
295             NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
296         CATID implCategories[] = {
297             CATID_Control,
298             CATID_PersistsToPropertyBag,
299             CATID_SafeForInitializing,
300             CATID_SafeForScripting,
301         };
302
303         pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
304                 sizeof(implCategories)/sizeof(CATID), implCategories);
305         pcr->Release();
306     }
307
308     // register type lib into the registry
309     ITypeLib *typeLib;
310
311 #ifdef BUILD_LOCALSERVER
312     // replace .exe by .tlb
313     strcpy(DllPath+DllPathLen-4, ".tlb");
314 #endif
315     
316 #ifndef OLE2ANSI
317     size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
318     if( typeLibPathLen > 0 )
319     {
320         LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
321         MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
322         if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
323 #ifndef BUILD_LOCALSERVER
324             return SELFREG_E_TYPELIB;
325         typeLib->Release();
326 #endif
327         CoTaskMemFree((void *)typeLibPath);
328     }
329 #else
330     if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
331         return SELFREG_E_TYPELIB;
332     typeLib->Release();
333 #endif
334
335     CoTaskMemFree((void *)psz_CLSID);
336
337     return S_OK;
338 };
339
340 #ifdef BUILD_LOCALSERVER
341
342 /*
343 ** easier to debug an application than a DLL on cygwin GDB :)
344 */
345 #include <iostream>
346
347 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
348 {
349     MSG msg;
350
351     if( FAILED(OleInitialize(NULL)) )
352     {
353         cerr << "cannot initialize OLE" << endl;
354         return 1;
355     }
356
357     h_instance = hInst;
358
359     if( FAILED(DllRegisterServer()) )
360     {
361         cerr << "cannot register Local Server" << endl;
362         return 1;
363     }
364
365     IUnknown *classProc = NULL;
366
367     if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
368         return 0;
369  
370     DWORD dwRegisterClassObject;
371
372     if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
373         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
374         return 0;
375
376     DWORD dwRegisterActiveObject;
377
378     if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
379                     ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
380         return 0;
381
382     classProc->Release();
383
384     /*
385     * Polling messages from event queue
386     */
387     while( S_FALSE == DllCanUnloadNow() )
388     {
389         while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
390         {
391             if( msg.message == WM_QUIT )
392                 break;  // Leave the PeekMessage while() loop
393
394             /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
395                 continue;*/
396
397             TranslateMessage(&msg);
398             DispatchMessage(&msg);
399         }
400
401         if(msg.message == WM_QUIT)
402             break;  // Leave the for() loop
403
404         WaitMessage();
405     }
406
407     if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
408         CoRevokeClassObject(dwRegisterClassObject);
409
410     // Reached on WM_QUIT message
411     CoUninitialize();
412     return ((int) msg.wParam);
413 };
414
415 #else
416
417 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
418 {
419     switch( fdwReason )
420     {
421         case DLL_PROCESS_ATTACH:
422             h_instance = (HINSTANCE)hModule;
423             break;
424
425         default:
426             break;
427     }
428     return TRUE;
429 };
430
431 #endif
432