]> git.sesse.net Git - vlc/blob - activex/main.cpp
- miscelleanous fixes and improvements
[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 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
38 \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
42 \r
43 #define GUID_STRLEN 39\r
44 \r
45 /*\r
46 ** MingW headers do not declare those\r
47 */\r
48 extern const CATID CATID_SafeForInitializing;\r
49 extern const CATID CATID_SafeForScripting;\r
50 \r
51 static LONG i_class_ref= 0;\r
52 static HINSTANCE h_instance= 0;\r
53 \r
54 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)\r
55 {\r
56     HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;\r
57 \r
58     *ppv = NULL;\r
59 \r
60     if( CLSID_VLCPlugin == rclsid )\r
61     {\r
62         VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);\r
63         hr = plugin->QueryInterface(riid, ppv);\r
64         plugin->Release();\r
65     }\r
66     return hr;\r
67 };\r
68 \r
69 STDAPI DllCanUnloadNow(VOID)\r
70 {\r
71     return (0 == i_class_ref) ? S_OK: S_FALSE;\r
72 };\r
73 \r
74 static LPCTSTR TStrFromGUID(REFGUID clsid) {\r
75     LPOLESTR oleStr;\r
76 \r
77     if( FAILED(StringFromIID(clsid, &oleStr)) )\r
78         return NULL;\r
79 \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
83 \r
84     LPTSTR pct_CLSID = NULL;\r
85 #ifndef OLE2ANSI\r
86     size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);\r
87     if( len > 0 )\r
88     {\r
89         pct_CLSID = (char *)CoTaskMemAlloc(len);\r
90         WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);\r
91     }\r
92 #else\r
93     size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);\r
94     if( len > 0 )\r
95     {\r
96         clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));\r
97         WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len);\r
98     }\r
99 #endif\r
100     CoTaskMemFree(oleStr);\r
101     return pct_CLSID;\r
102 };\r
103 \r
104 static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)\r
105 {\r
106     HKEY childKey;\r
107     if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,\r
108                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )\r
109     {\r
110         return childKey;\r
111     }\r
112     return NULL;\r
113 };\r
114 \r
115 STDAPI DllUnregisterServer(VOID)\r
116 {\r
117     // unregister type lib from the registry\r
118     UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);\r
119 \r
120     // remove component categories we supports\r
121     ICatRegister *pcr;\r
122     if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, \r
123             NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {\r
124         CATID implCategories[] = {\r
125             CATID_Control,\r
126             CATID_PersistsToPropertyBag,\r
127             CATID_SafeForInitializing,\r
128             CATID_SafeForScripting,\r
129         };\r
130 \r
131         pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,\r
132                 sizeof(implCategories)/sizeof(CATID), implCategories);\r
133         pcr->Release();\r
134     }\r
135 \r
136     SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));\r
137     SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));\r
138 \r
139     LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);\r
140 \r
141     if( NULL == psz_CLSID )\r
142         return E_OUTOFMEMORY;\r
143 \r
144     HKEY hClsIDKey;\r
145     if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )\r
146     {\r
147         SHDeleteKey(hClsIDKey, psz_CLSID);\r
148         RegCloseKey(hClsIDKey);\r
149     }\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     LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);\r
159 \r
160     if( NULL == psz_CLSID )\r
161         return E_OUTOFMEMORY;\r
162 \r
163     HKEY hBaseKey;\r
164 \r
165     if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )\r
166         return E_FAIL;\r
167 \r
168     HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);\r
169     if( NULL != hClassKey )\r
170     {\r
171         HKEY hSubKey;\r
172 \r
173         // default key value\r
174         RegSetValueEx(hClassKey, NULL, 0, REG_SZ,\r
175                 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));\r
176 \r
177         // Control key value\r
178         hSubKey = keyCreate(hClassKey, TEXT("Control"));\r
179         RegCloseKey(hSubKey);\r
180 \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
188 \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
193 \r
194         // Programmable key value\r
195         hSubKey = keyCreate(hClassKey, TEXT("Programmable"));\r
196         RegCloseKey(hSubKey);\r
197 \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
203 \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
209 \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
215 \r
216         // TypeLib key value\r
217         LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);\r
218         if( NULL != psz_LIBID )\r
219         {\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
224         }\r
225         RegCloseKey(hClassKey);\r
226     }\r
227     RegCloseKey(hBaseKey);\r
228 \r
229     hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));\r
230     if( NULL != hBaseKey )\r
231     {\r
232         // default key value\r
233         RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,\r
234                 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));\r
235 \r
236         HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));\r
237         if( NULL != hSubKey )\r
238         {\r
239             // default key value\r
240             RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
241                     (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);\r
242 \r
243             RegCloseKey(hSubKey);\r
244         }\r
245         hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));\r
246         if( NULL != hSubKey )\r
247         {\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
251 \r
252             RegCloseKey(hSubKey);\r
253         }\r
254         RegCloseKey(hBaseKey);\r
255     }\r
256 \r
257     hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));\r
258     if( NULL != hBaseKey )\r
259     {\r
260         // default key value\r
261         RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,\r
262                 (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));\r
263 \r
264         HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));\r
265         if( NULL != hSubKey )\r
266         {\r
267             // default key value\r
268             RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
269                     (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);\r
270 \r
271             RegCloseKey(hSubKey);\r
272         }\r
273         RegCloseKey(hBaseKey);\r
274     }\r
275 \r
276     // indicate which component categories we support\r
277     ICatRegister *pcr;\r
278     if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, \r
279             NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {\r
280         CATID implCategories[] = {\r
281             CATID_Control,\r
282             CATID_PersistsToPropertyBag,\r
283             CATID_SafeForInitializing,\r
284             CATID_SafeForScripting,\r
285         };\r
286 \r
287         pcr->RegisterClassImplCategories(CLSID_VLCPlugin,\r
288                 sizeof(implCategories)/sizeof(CATID), implCategories);\r
289         pcr->Release();\r
290     }\r
291 \r
292     // register type lib into the registry\r
293     ITypeLib *typeLib;\r
294     if( SUCCEEDED(LoadTypeLibEx(OLESTR("")COMDLLPATH, REGKIND_REGISTER, &typeLib)) )\r
295         typeLib->Release();\r
296 \r
297     return S_OK;\r
298 };\r
299 \r
300 #ifdef BUILD_LOCALSERVER\r
301 \r
302 /*\r
303 ** easier to debug an application than a DLL on cygwin GDB :)\r
304 */\r
305 #include <stream.h>\r
306 \r
307 STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)\r
308 {\r
309     MSG msg;\r
310 \r
311     if( FAILED(OleInitialize(NULL)) )\r
312     {\r
313         cerr << "cannot initialize OLE" << endl;\r
314         return 1;\r
315     }\r
316 \r
317     IUnknown *classProc = NULL;\r
318 \r
319     if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )\r
320         return 0;\r
321  \r
322     DWORD dwRegisterClassObject;\r
323 \r
324     if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,\r
325         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )\r
326         return 0;\r
327 \r
328     DWORD dwRegisterActiveObject;\r
329 \r
330     if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,\r
331                     ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )\r
332         return 0;\r
333 \r
334     classProc->Release();\r
335 \r
336     /*\r
337     * Polling messages from event queue\r
338     */\r
339     while( S_FALSE == DllCanUnloadNow() )\r
340     {\r
341         while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )\r
342         {\r
343             if( msg.message == WM_QUIT )\r
344                 break;  // Leave the PeekMessage while() loop\r
345 \r
346             /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))\r
347                 continue;*/\r
348 \r
349             TranslateMessage(&msg);\r
350             DispatchMessage(&msg);\r
351         }\r
352 \r
353         if(msg.message == WM_QUIT)\r
354             break;  // Leave the for() loop\r
355 \r
356         WaitMessage();\r
357     }\r
358 \r
359     if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )\r
360         CoRevokeClassObject(dwRegisterClassObject);\r
361 \r
362     // Reached on WM_QUIT message\r
363     CoUninitialize();\r
364     return ((int) msg.wParam);\r
365 };\r
366 \r
367 #else\r
368 \r
369 STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )\r
370 {\r
371     switch( fdwReason )\r
372     {\r
373         case DLL_PROCESS_ATTACH:\r
374             h_instance = (HINSTANCE)hModule;\r
375             break;\r
376 \r
377         default:\r
378             break;\r
379     }\r
380     return TRUE;\r
381 };\r
382 \r
383 #endif\r
384 \r