bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / plugin / win / winmgr.cxx
blobb84315e1873f9f4f33d57e065e9b1c9b2d08161e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <prewin.h>
31 #include <postwin.h>
33 #include "vcl/svapp.hxx"
34 #include "tools/urlobj.hxx"
35 #include "osl/mutex.hxx"
37 #include "rtl/string.hxx"
38 #include "rtl/ustring.hxx"
39 #include "rtl/ustrbuf.hxx"
41 #include "plugin/impl.hxx"
43 #if defined _MSC_VER
44 #pragma warning (push,1)
45 #pragma warning (disable:4005)
46 #endif
48 #include <string.h>
49 #include <tchar.h>
50 #include <objbase.h>
52 #if defined _MSC_VER
53 #pragma warning (pop)
54 #endif
56 #include <list>
57 #include <map>
58 #include <algorithm>
61 using namespace std;
62 using namespace osl;
63 using namespace com::sun::star::uno;
64 using namespace com::sun::star::plugin;
67 typedef map< OString, OUString, less< OString > > PluginLocationMap;
70 static void addPluginsFromPath( const TCHAR * pPluginsPath, PluginLocationMap & rPlugins )
72 // append dll name pattern we are looking for
73 TCHAR arPluginsPath[MAX_PATH];
74 arPluginsPath[0] = 0;
76 if (::rtl_str_indexOfStr( pPluginsPath, "%programfiles%" ) == 0)
78 const char * p = ::getenv( "ProgramFiles" );
79 if (p)
81 ::lstrcpy( arPluginsPath, p );
82 pPluginsPath += 14;
85 ::lstrcat( arPluginsPath, pPluginsPath );
86 ::lstrcat( arPluginsPath, _T("\\") );
88 TCHAR arPluginsPattern[MAX_PATH];
89 ::lstrcpy( arPluginsPattern, arPluginsPath );
90 ::lstrcat( arPluginsPattern, _T("NP*.DLL") );
92 WIN32_FIND_DATA aFindData;
93 HANDLE hFind = ::FindFirstFile( arPluginsPattern, &aFindData );
95 while (hFind != INVALID_HANDLE_VALUE)
97 OString aName = OString( aFindData.cFileName ).toAsciiLowerCase();
99 // no netscape default plugin anymore...
100 // and no double plugin dlls
101 if ( !aName.equals( "npnul32.dll" ) &&
102 ! aName.equals( "npnrvp.dll" ) &&
103 rPlugins.find( aName ) == rPlugins.end())
105 TCHAR arComplete[MAX_PATH];
106 ::lstrcpy( arComplete, arPluginsPath );
107 ::lstrcat( arComplete, aFindData.cFileName );
109 OUString path( OStringToOUString( arComplete, RTL_TEXTENCODING_MS_1252 ) );
110 rPlugins[ aName ] = path;
113 if (! ::FindNextFile( hFind, &aFindData ))
114 break;
117 if (hFind != INVALID_HANDLE_VALUE)
118 ::FindClose( hFind );
121 static void addPluginsFromPath( const OUString & rPath, PluginLocationMap & rPlugins )
123 TCHAR arPluginsPath[MAX_PATH];
124 DWORD dwPluginsPathSize = sizeof(arPluginsPath);
125 arPluginsPath[dwPluginsPathSize-1] = 0;
127 OString aStr( OUStringToOString( rPath, RTL_TEXTENCODING_MS_1252 ) );
128 ::strncpy( arPluginsPath, aStr.getStr(), dwPluginsPathSize );
130 addPluginsFromPath( arPluginsPath, rPlugins );
135 static void add_IE_Plugins( PluginLocationMap & rPlugins )
137 HKEY hKey;
138 TCHAR arCurrent[MAX_PATH];
139 DWORD dwType, dwCurrentSize = sizeof(arCurrent);
141 if (::RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\IE4\\SETUP"),
142 0, KEY_READ, &hKey ) == ERROR_SUCCESS)
144 if (::RegQueryValueEx( hKey, _T("Path"), NULL, &dwType,
145 (LPBYTE)arCurrent, &dwCurrentSize ) == ERROR_SUCCESS &&
146 (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
148 // add \\Plugins
149 ::lstrcat( arCurrent, _T("\\Plugins") );
151 addPluginsFromPath( arCurrent, rPlugins );
153 ::RegCloseKey( hKey );
158 static void add_NS_keys( HKEY hKey, PluginLocationMap & rPlugins )
160 TCHAR value[MAX_PATH];
161 DWORD dwType, size;
163 // 4.7
164 size = sizeof(value);
165 if (::RegQueryValueEx(
166 hKey, _T("Plugins Directory"), NULL, &dwType,
167 (LPBYTE)value, &size ) == ERROR_SUCCESS &&
168 (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
170 addPluginsFromPath( value, rPlugins );
172 // 6
173 size = sizeof(value);
174 if (::RegQueryValueEx(
175 hKey, _T("Install Directory"), NULL, &dwType,
176 (LPBYTE)value, &size ) == ERROR_SUCCESS &&
177 (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
179 int n = size / sizeof (TCHAR);
180 if ('\\' != value[ n -2 ])
182 value[ n -1 ] = '\\';
183 value[ n ] = 0;
185 addPluginsFromPath( ::lstrcat( value, _T("Plugins") ), rPlugins );
187 size = sizeof(value);
188 if (::RegQueryValueEx(
189 hKey, _T("Plugins"), NULL, &dwType,
190 (LPBYTE)value, &size ) == ERROR_SUCCESS &&
191 (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
193 addPluginsFromPath( value, rPlugins );
197 static void add_NS_lookupRecursive( HKEY hKey, PluginLocationMap & rPlugins )
199 add_NS_keys( hKey, rPlugins );
201 TCHAR keyName[MAX_PATH];
202 DWORD dwIndex = 0, size = sizeof (keyName);
204 while (::RegEnumKeyEx( hKey, dwIndex, keyName, &size, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS)
206 size = sizeof (keyName);
207 HKEY hSubKey;
208 if (::RegOpenKeyEx( hKey, keyName, 0, KEY_READ, &hSubKey ) == ERROR_SUCCESS)
210 add_NS_lookupRecursive( hSubKey, rPlugins );
211 ::RegCloseKey( hSubKey );
213 ++dwIndex;
217 static void add_MozPlugin( HKEY hKey, PluginLocationMap & rPlugins )
219 TCHAR value[MAX_PATH];
220 DWORD dwType, size;
222 size = sizeof(value);
223 if (::RegQueryValueEx(
224 hKey, _T("Path"), NULL, &dwType,
225 (LPBYTE)value, &size ) == ERROR_SUCCESS &&
226 (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
228 OUString aUPath( OStringToOUString( value, RTL_TEXTENCODING_MS_1252 ) );
229 INetURLObject aURL( aUPath );
230 OString aName( OUStringToOString( aURL.GetName().toAsciiLowerCase(), RTL_TEXTENCODING_MS_1252 ) );
232 // no netscape default plugin anymore...
233 // and no double plugin dlls
234 if ( !aName.equals( "npnul32.dll" ) &&
235 ! aName.equals( "npnrvp.dll" ) &&
236 rPlugins.find( aName ) == rPlugins.end())
238 rPlugins[ aName ] = aUPath;
242 static void add_MozillaPlugin( HKEY hKey, PluginLocationMap & rPlugins )
244 TCHAR keyName[MAX_PATH];
245 DWORD dwIndex = 0, size = sizeof (keyName);
247 while (::RegEnumKeyEx( hKey, dwIndex, keyName, &size, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS)
249 size = sizeof (keyName);
250 HKEY hSubKey;
251 if (::RegOpenKeyEx( hKey, keyName, 0, KEY_READ, &hSubKey ) == ERROR_SUCCESS)
253 add_MozPlugin( hSubKey, rPlugins );
254 ::RegCloseKey( hSubKey );
256 ++dwIndex;
260 static void add_NS_Plugins( PluginLocationMap & rPlugins )
262 HKEY hKey;
263 // Netscape
264 if (::RegOpenKeyEx(
265 HKEY_LOCAL_MACHINE, _T("Software\\Netscape"),
266 0, KEY_READ, &hKey ) == ERROR_SUCCESS)
268 add_NS_lookupRecursive( hKey, rPlugins );
269 ::RegCloseKey( hKey );
271 // Mozilla
272 if (::RegOpenKeyEx(
273 HKEY_LOCAL_MACHINE, _T("Software\\Mozilla"),
274 0, KEY_READ, &hKey ) == ERROR_SUCCESS)
276 add_NS_lookupRecursive( hKey, rPlugins );
277 ::RegCloseKey( hKey );
279 // Mozilla - plugins
280 if (::RegOpenKeyEx(
281 HKEY_LOCAL_MACHINE, _T("Software\\MozillaPlugins"),
282 0, KEY_READ, &hKey ) == ERROR_SUCCESS)
284 add_MozillaPlugin( hKey, rPlugins );
285 ::RegCloseKey( hKey );
290 static void add_SO_Plugins( PluginLocationMap & rPlugins )
292 const Sequence< OUString > & rPaths = PluginManager::getAdditionalSearchPaths();
294 const OUString * pPaths = rPaths.getConstArray();
295 for ( UINT32 nPos = rPaths.getLength(); nPos--; )
297 addPluginsFromPath( pPaths[nPos], rPlugins );
302 Sequence< PluginDescription > XPluginManager_Impl::impl_getPluginDescriptions() throw(css::uno::RuntimeException, std::exception)
304 Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
305 static Sequence<PluginDescription > s_aDescriptions( 0 );
306 static bool s_bInit = FALSE;
308 if (! s_bInit)
310 // collect all distinct plugin dlls
311 PluginLocationMap aPlugins;
312 add_SO_Plugins( aPlugins );
313 add_NS_Plugins( aPlugins );
314 add_IE_Plugins( aPlugins );
316 // collect mime types of plugin dlls
317 for ( PluginLocationMap::iterator iPos( aPlugins.begin() );
318 iPos != aPlugins.end();
319 ++iPos )
321 TCHAR arFileName[MAX_PATH];
322 DWORD dwDummy, dwSize;
324 // DLL name
325 OUString aName( (*iPos).second.getStr() );
327 OString aStr( OUStringToOString( aName, RTL_TEXTENCODING_MS_1252 ) );
328 ::strcpy( arFileName, aStr.getStr() );
329 dwSize = ::GetFileVersionInfoSize( arFileName, &dwDummy );
331 if ( !dwSize )
332 continue;
334 char * pVersionData = new char[dwSize];
335 if (::GetFileVersionInfo( arFileName, 0, dwSize, pVersionData))
337 // optional comment
338 OUString aComment;
340 TCHAR * pInfo = NULL, * pInfo2 = NULL;
341 UINT nSize = 0;
342 if (::VerQueryValue( pVersionData, _T("\\StringFileInfo\\040904E4\\ProductName"),
343 (void**)&pInfo, &nSize ) && pInfo)
345 aComment.operator=( OStringToOUString( OString(pInfo), RTL_TEXTENCODING_MS_1252 ) );
348 // mandatory mime type and file extensions
349 if (::VerQueryValue( pVersionData, _T("\\StringFileInfo\\040904E4\\MIMEType"),
350 (void**)&pInfo, &nSize ) && pInfo &&
351 ::VerQueryValue( pVersionData, _T("\\StringFileInfo\\040904E4\\FileExtents"),
352 (void**)&pInfo2, &nSize ) && pInfo2)
354 OString aExt( pInfo2 );
355 OString aMIME( pInfo );
356 aMIME.trim();
358 // count mime tokens
359 USHORT nToken = 0;
360 if (aMIME.getLength())
362 ++nToken;
363 for ( sal_Int32 n = aMIME.getLength(); n--; )
365 if (aMIME[ n ] == '|')
367 ++nToken;
371 sal_Int32 nIndex = 0, nIndex2 = 0;
373 UINT32 nStart = s_aDescriptions.getLength();
374 s_aDescriptions.realloc( nStart + nToken );
375 PluginDescription* pDescriptions = s_aDescriptions.getArray();
376 // for every MIME Type
377 sal_Int32 nTok = 0;
378 while (true)
380 if (nIndex < 0 || nIndex2 < 0)
381 break;
383 PluginDescription & rDescr = pDescriptions[nStart+nTok];
384 OString aMIMEToken( aMIME.getToken( 0, '|', nIndex ) );
385 OString aExtToken2( aExt.getToken( 0, '|', nIndex2 ) );
386 if( aMIMEToken.isEmpty() || aExtToken2.isEmpty() )
387 continue;
389 rDescr.Mimetype = OUString(
390 aMIMEToken.getStr(), aMIMEToken.getLength(), RTL_TEXTENCODING_MS_1252 );
391 if (! rDescr.Mimetype.getLength())
392 break;
394 OUString aExtToken( aExtToken2.getStr(), aExtToken2.getLength(), RTL_TEXTENCODING_MS_1252 );
395 rDescr.PluginName = aName;
396 rDescr.Description = aComment;
398 sal_Int32 nPos = 0, nLen = aExtToken.getLength();
399 OUString aExtensions = nLen ? OUString("*.") : OUString("*.*");
401 for ( ; nPos < nLen; ++nPos )
403 sal_Unicode c = aExtToken[nPos];
404 switch (c)
406 case ',':
407 case ';':
408 aExtensions += ";*.";
409 case ' ':
410 break;
411 case '*':
412 if (nPos < (nLen-1) && aExtToken[ nPos+1 ] == '.')
414 ++nPos;
415 break;
417 default:
418 aExtensions += OUString( &c, 1 );
421 rDescr.Extension = aExtensions;
423 ++nTok;
426 if (nToken != nTok)
428 s_aDescriptions.realloc( nTok );
431 #if OSL_DEBUG_LEVEL > 1
432 else
433 OSL_FAIL( "### cannot get MIME type or extensions!" );
434 #endif
436 delete[] pVersionData;
439 s_bInit = TRUE;
441 return s_aDescriptions;
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */