]> git.sesse.net Git - vlc/blob - activex/main.cpp
Removes trailing spaces. Removes tabs.
[vlc] / activex / main.cpp
1 /*****************************************************************************
2  * main.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #include "plugin.h"
24 #include "utils.h"
25
26 #include <stdio.h>
27
28 #include <comcat.h>
29 #include <windows.h>
30 #include <shlwapi.h>
31
32 #include <tchar.h>
33 #include <guiddef.h>
34
35 using namespace std;
36
37 #define COMPANY_STR "VideoLAN"
38 #define PROGRAM_STR "VLCPlugin"
39 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
40
41 #define THREADING_MODEL "Apartment"
42 #define MISC_STATUS     "131473"
43
44 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
45
46 #define GUID_STRLEN 39
47
48 /*
49 ** MingW headers & libs do not declare those
50 */
51 static DEFINE_GUID(_CATID_InternetAware,       0x0DE86A58, 0x2BAA, 0x11CF, 0xA2, 0x29, 0x00,0xAA,0x00,0x3D,0x73,0x52);
52 static DEFINE_GUID(_CATID_SafeForInitializing, 0x7DD95802, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
53 static DEFINE_GUID(_CATID_SafeForScripting,    0x7DD95801, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
54
55 static LONG i_class_ref= 0;
56 static HINSTANCE h_instance= 0;
57
58 HMODULE DllGetModule()
59 {
60     return h_instance;
61 };
62
63 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
64 {
65     HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
66
67     *ppv = NULL;
68
69     if( (CLSID_VLCPlugin == rclsid )
70      || ( CLSID_VLCPlugin2 == rclsid) )
71     {
72         VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
73         hr = plugin->QueryInterface(riid, ppv);
74         plugin->Release();
75     }
76     return hr;
77 };
78
79 STDAPI DllCanUnloadNow(VOID)
80 {
81     return (0 == i_class_ref) ? S_OK: S_FALSE;
82 };
83
84 static inline HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
85 {
86     HKEY childKey;
87     if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
88                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
89     {
90         return childKey;
91     }
92     return NULL;
93 };
94
95 static inline HKEY keySet(HKEY hKey, LPCTSTR valueName, const void *s, size_t len, DWORD dwType = REG_SZ)
96 {
97     if( NULL != hKey )
98     {
99         RegSetValueEx(hKey, valueName, 0, dwType,
100             (const BYTE*)s, len);
101     }
102     return hKey;
103 };
104
105 static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len, DWORD dwType = REG_SZ)
106 {
107     return keySet(hKey, NULL, s, len, dwType);
108 };
109
110 static inline HKEY keySetDef(HKEY hKey, LPCTSTR s)
111 {
112     return keySetDef(hKey, s, sizeof(TCHAR)*(_tcslen(s)+1), REG_SZ);
113 };
114
115 static inline HKEY keyClose(HKEY hKey)
116 {
117     if( NULL != hKey )
118     {
119         RegCloseKey(hKey);
120     }
121     return NULL;
122 };
123
124 static void UnregisterProgID(REFCLSID rclsid, unsigned int version)
125 {
126     OLECHAR szCLSID[GUID_STRLEN];
127
128     StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
129
130     TCHAR progId[sizeof(PROGID_STR)+16];
131     _stprintf(progId, TEXT("%s.%u"), TEXT(PROGID_STR), version);
132
133     SHDeleteKey(HKEY_CLASSES_ROOT, progId);
134
135     HKEY hClsIDKey;
136     if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
137     {
138         SHDeleteKey(hClsIDKey, szCLSID);
139         RegCloseKey(hClsIDKey);
140     }
141 };
142
143 STDAPI DllUnregisterServer(VOID)
144 {
145     // unregister type lib from the registry
146     UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
147
148     // remove component categories we supports
149     ICatRegister *pcr;
150     if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
151             NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
152         CATID implCategories[] = {
153             CATID_Control,
154             CATID_PersistsToPropertyBag,
155             _CATID_InternetAware,
156             _CATID_SafeForInitializing,
157             _CATID_SafeForScripting,
158         };
159
160         pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
161                 sizeof(implCategories)/sizeof(CATID), implCategories);
162         pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
163                 sizeof(implCategories)/sizeof(CATID), implCategories);
164         pcr->Release();
165     }
166
167     SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
168
169     UnregisterProgID(CLSID_VLCPlugin, 2);
170     UnregisterProgID(CLSID_VLCPlugin2, 1);
171
172     return S_OK;
173 };
174
175 static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, LPCTSTR path, size_t pathLen)
176 {
177     TCHAR progId[sizeof(PROGID_STR)+16];
178     _stprintf(progId, TEXT("%s.%u"), TEXT(PROGID_STR), version);
179
180     TCHAR description[sizeof(DESCRIPTION)+16];
181     _stprintf(description, TEXT("%s v%u"), TEXT(DESCRIPTION), version);
182
183     HKEY hClassKey;
184     {
185         OLECHAR szCLSID[GUID_STRLEN];
186
187         StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
188
189         HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
190         if( NULL != hProgKey )
191         {
192             // default key value
193             keySetDef(hProgKey, description);
194
195             keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
196                 szCLSID,
197                 sizeof(szCLSID)));
198
199             //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
200  
201             RegCloseKey(hProgKey);
202         }
203         if( isDefault )
204         {
205             hProgKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
206             if( NULL != hProgKey )
207             {
208                 // default key value
209                 keySetDef(hProgKey, description);
210
211                 keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
212                     szCLSID,
213                     sizeof(szCLSID)));
214
215                 keyClose(keySetDef(keyCreate(hProgKey, TEXT("CurVer")),
216                     progId));
217             }
218         }
219         hClassKey = keyCreate(hParent, szCLSID);
220     }
221     if( NULL != hClassKey )
222     {
223         // default key value
224         keySetDef(hClassKey, description);
225
226         // Control key value
227         keyClose(keyCreate(hClassKey, TEXT("Control")));
228
229         // Insertable key value
230         //keyClose(keyCreate(hClassKey, TEXT("Insertable")));
231
232         // ToolboxBitmap32 key value
233         {
234             TCHAR iconPath[pathLen+3];
235             memcpy(iconPath, path, sizeof(TCHAR)*pathLen);
236             _tcscpy(iconPath+pathLen, TEXT(",1"));
237             keyClose(keySetDef(keyCreate(hClassKey,
238                 TEXT("ToolboxBitmap32")),
239                 iconPath, sizeof(iconPath)));
240         }
241
242 #ifdef BUILD_LOCALSERVER
243         // LocalServer32 key value
244         keyClose(keySetDef(keyCreate(hClassKey,
245             TEXT("LocalServer32"), path, sizeof(TCHAR)*(pathLen+1))));
246 #else
247         // InprocServer32 key value
248         {
249             HKEY hSubKey = keySetDef(keyCreate(hClassKey,
250                 TEXT("InprocServer32")),
251                 path, sizeof(TCHAR)*(pathLen+1));
252             keySet(hSubKey,
253                 TEXT("ThreadingModel"),
254                 TEXT(THREADING_MODEL), sizeof(TEXT(THREADING_MODEL)));
255             keyClose(hSubKey);
256         }
257 #endif
258
259         // MiscStatus key value
260         keyClose(keySetDef(keyCreate(hClassKey,
261             TEXT("MiscStatus\\1")),
262             TEXT(MISC_STATUS), sizeof(TEXT(MISC_STATUS))));
263
264         // Programmable key value
265         keyClose(keyCreate(hClassKey, TEXT("Programmable")));
266
267         // ProgID key value
268         keyClose(keySetDef(keyCreate(hClassKey,
269             TEXT("ProgID")),
270             progId));
271
272         // VersionIndependentProgID key value
273         keyClose(keySetDef(keyCreate(hClassKey,
274             TEXT("VersionIndependentProgID")),
275             TEXT(PROGID_STR), sizeof(TEXT(PROGID_STR))));
276
277         // Version key value
278         keyClose(keySetDef(keyCreate(hClassKey,
279             TEXT("Version")),
280             TEXT("1.0")));
281
282         // TypeLib key value
283         OLECHAR szLIBID[GUID_STRLEN];
284
285         StringFromGUID2(LIBID_AXVLC, szLIBID, GUID_STRLEN);
286
287         keyClose(keySetDef(keyCreate(hClassKey,
288                 TEXT("TypeLib")),
289                 szLIBID, sizeof(szLIBID)));
290  
291         RegCloseKey(hClassKey);
292     }
293     return S_OK;
294 }
295
296 STDAPI DllRegisterServer(VOID)
297 {
298     DllUnregisterServer();
299
300     TCHAR DllPath[MAX_PATH];
301     DWORD DllPathLen=GetModuleFileName(h_instance, DllPath, MAX_PATH) ;
302     if( 0 == DllPathLen )
303         return E_UNEXPECTED;
304
305     HKEY hBaseKey;
306
307     if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
308         return SELFREG_E_CLASS;
309
310     RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
311     RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
312
313     RegCloseKey(hBaseKey);
314
315     // indicate which component categories we support
316     ICatRegister *pcr;
317     if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
318             NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
319         CATID implCategories[] = {
320             CATID_Control,
321             CATID_PersistsToPropertyBag,
322             _CATID_InternetAware,
323             _CATID_SafeForInitializing,
324             _CATID_SafeForScripting,
325         };
326
327         pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
328                 sizeof(implCategories)/sizeof(CATID), implCategories);
329         pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
330                 sizeof(implCategories)/sizeof(CATID), implCategories);
331         pcr->Release();
332     }
333
334 #ifdef BUILD_LOCALSERVER
335     // replace .exe by .tlb
336     _tcscpy(DllPath+DllPathLen-4, TEXT(".tlb"));
337 #endif
338
339     // register type lib into the registry
340     ITypeLib *typeLib;
341
342     HRESULT result = LoadTypeLibEx(DllPath, REGKIND_REGISTER, &typeLib);
343     if( SUCCEEDED(result) )
344         typeLib->Release();
345
346     return result;
347 };
348
349 #ifdef BUILD_LOCALSERVER
350
351 /*
352 ** easier to debug an application than a DLL on cygwin GDB :)
353 */
354 #include <iostream>
355
356 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
357 {
358     MSG msg;
359
360     if( FAILED(OleInitialize(NULL)) )
361     {
362         cerr << "cannot initialize OLE" << endl;
363         return 1;
364     }
365
366     h_instance = hInst;
367
368     if( FAILED(DllRegisterServer()) )
369     {
370         cerr << "cannot register Local Server" << endl;
371         return 1;
372     }
373
374     IUnknown *classProc = NULL;
375
376     if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
377         return 0;
378  
379     DWORD dwRegisterClassObject;
380     DWORD dwRegisterClassObject2;
381
382     if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
383         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
384         return 0;
385
386     DWORD dwRegisterActiveObject;
387
388     if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
389                     ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
390         return 0;
391
392     if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
393                     ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
394         return 0;
395
396     classProc->Release();
397
398     /*
399     * Polling messages from event queue
400     */
401     while( S_FALSE == DllCanUnloadNow() )
402     {
403         while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
404         {
405             if( msg.message == WM_QUIT )
406                 break;  // break out PeekMessage loop
407
408             /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
409                 continue;*/
410
411             TranslateMessage(&msg);
412             DispatchMessage(&msg);
413         }
414
415         if(msg.message == WM_QUIT)
416             break;  // break out main loop
417
418         WaitMessage();
419     }
420
421     if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
422         CoRevokeClassObject(dwRegisterClassObject);
423
424     if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
425         CoRevokeClassObject(dwRegisterClassObject2);
426
427     // Reached on WM_QUIT message
428     OleUninitialize();
429     return ((int) msg.wParam);
430 };
431
432 #else
433
434 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
435 {
436     switch( fdwReason )
437     {
438         case DLL_PROCESS_ATTACH:
439             h_instance = (HINSTANCE)hModule;
440             break;
441
442         default:
443             break;
444     }
445     return TRUE;
446 };
447
448 #endif
449