]> git.sesse.net Git - vlc/blob - activex/main.cpp
wx: (hopefully) fixed a compilation error, reported by robux
[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 #ifndef OLE2ANSI
311     size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
312     if( typeLibPathLen > 0 )
313     {
314         LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
315         MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
316         if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
317             return SELFREG_E_TYPELIB;
318         typeLib->Release();
319         CoTaskMemFree((void *)typeLibPath);
320     }
321 #else
322     if( FAILED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )
323         return SELFREG_E_TYPELIB;
324     typeLib->Release();
325 #endif
326
327     CoTaskMemFree((void *)psz_CLSID);
328
329     return S_OK;
330 };
331
332 #ifdef BUILD_LOCALSERVER
333
334 /*
335 ** easier to debug an application than a DLL on cygwin GDB :)
336 */
337 #include <iostream>
338
339 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
340 {
341     MSG msg;
342
343     if( FAILED(OleInitialize(NULL)) )
344     {
345         cerr << "cannot initialize OLE" << endl;
346         return 1;
347     }
348
349     h_instance = hInst;
350
351     if( FAILED(DllRegisterServer()) )
352     {
353         cerr << "cannot register Local Server" << endl;
354         return 1;
355     }
356
357     IUnknown *classProc = NULL;
358
359     if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
360         return 0;
361  
362     DWORD dwRegisterClassObject;
363
364     if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
365         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
366         return 0;
367
368     DWORD dwRegisterActiveObject;
369
370     if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
371                     ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
372         return 0;
373
374     classProc->Release();
375
376     /*
377     * Polling messages from event queue
378     */
379     while( S_FALSE == DllCanUnloadNow() )
380     {
381         while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
382         {
383             if( msg.message == WM_QUIT )
384                 break;  // Leave the PeekMessage while() loop
385
386             /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
387                 continue;*/
388
389             TranslateMessage(&msg);
390             DispatchMessage(&msg);
391         }
392
393         if(msg.message == WM_QUIT)
394             break;  // Leave the for() loop
395
396         WaitMessage();
397     }
398
399     if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
400         CoRevokeClassObject(dwRegisterClassObject);
401
402     // Reached on WM_QUIT message
403     CoUninitialize();
404     return ((int) msg.wParam);
405 };
406
407 #else
408
409 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
410 {
411     switch( fdwReason )
412     {
413         case DLL_PROCESS_ATTACH:
414             h_instance = (HINSTANCE)hModule;
415             break;
416
417         default:
418             break;
419     }
420     return TRUE;
421 };
422
423 #endif
424