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