1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2010 by Sun Microsystems, Inc. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_shell.hxx" 30 #include "internal/global.hxx" 31 #include "internal/PropertyHdl.hxx" 32 #include "internal/fileextensions.hxx" 33 #include "internal/metainforeader.hxx" 34 #include "internal/utilities.hxx" 35 #include "internal/config.hxx" 36 37 #include <propkey.h> 38 #include <propvarutil.h> 39 40 #include <malloc.h> 41 #include <strsafe.h> 42 43 #include "internal/stream_helper.hxx" 44 45 //--------------------------- 46 // Module global 47 //--------------------------- 48 long g_DllRefCnt = 0; 49 HINSTANCE g_hModule = NULL; 50 51 // 52 // Map of property keys to the locations of their value(s) in the .??? XML schema 53 // 54 struct PROPERTYMAP 55 { 56 PROPERTYKEY key; 57 PCWSTR pszXPathParent; 58 PCWSTR pszValueNodeName; 59 }; 60 61 PROPERTYMAP g_rgPROPERTYMAP[] = 62 { 63 { PKEY_Title, L"OpenOffice.org", L"Title" }, 64 { PKEY_Author, L"OpenOffice.org", L"Author" }, 65 { PKEY_Subject, L"OpenOffice.org", L"Subject" }, 66 { PKEY_Keywords, L"OpenOffice.org", L"Keyword" }, 67 { PKEY_Comment, L"OpenOffice.org", L"Comments" }, 68 }; 69 70 size_t gPropertyMapTableSize = sizeof(g_rgPROPERTYMAP)/sizeof(g_rgPROPERTYMAP[0]); 71 72 //---------------------------- 73 // 74 //---------------------------- 75 76 CPropertyHdl::CPropertyHdl( long nRefCnt ) : 77 m_RefCnt( nRefCnt ), 78 m_pCache( NULL ) 79 { 80 OutputDebugStringFormat( "CPropertyHdl: CTOR\n" ); 81 InterlockedIncrement( &g_DllRefCnt ); 82 } 83 84 //---------------------------- 85 // 86 //---------------------------- 87 88 CPropertyHdl::~CPropertyHdl() 89 { 90 if ( m_pCache ) 91 { 92 m_pCache->Release(); 93 m_pCache = NULL; 94 } 95 InterlockedDecrement( &g_DllRefCnt ); 96 } 97 98 //----------------------------- 99 // IUnknown methods 100 //----------------------------- 101 HRESULT STDMETHODCALLTYPE CPropertyHdl::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) 102 { 103 *ppvObject = 0; 104 105 if (IID_IUnknown == riid || IID_IPropertyStore == riid) 106 { 107 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (IID_IPropertyStore)\n" ); 108 IUnknown* pUnk = static_cast<IPropertyStore*>(this); 109 pUnk->AddRef(); 110 *ppvObject = pUnk; 111 return S_OK; 112 } 113 else if (IID_IPropertyStoreCapabilities == riid) 114 { 115 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (IID_IPropertyStoreCapabilities)\n" ); 116 IUnknown* pUnk = static_cast<IPropertyStore*>(this); 117 pUnk->AddRef(); 118 *ppvObject = pUnk; 119 return S_OK; 120 } 121 else if (IID_IInitializeWithStream == riid) 122 { 123 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (IID_IInitializeWithStream)\n" ); 124 IUnknown* pUnk = static_cast<IInitializeWithStream*>(this); 125 pUnk->AddRef(); 126 *ppvObject = pUnk; 127 return S_OK; 128 } 129 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (something different)\n" ); 130 131 return E_NOINTERFACE; 132 } 133 134 //---------------------------- 135 ULONG STDMETHODCALLTYPE CPropertyHdl::AddRef( void ) 136 { 137 return InterlockedIncrement( &m_RefCnt ); 138 } 139 140 //---------------------------- 141 ULONG STDMETHODCALLTYPE CPropertyHdl::Release( void ) 142 { 143 long refcnt = InterlockedDecrement( &m_RefCnt ); 144 145 if ( 0 == m_RefCnt ) 146 delete this; 147 148 return refcnt; 149 } 150 151 //----------------------------- 152 // IPropertyStore 153 //----------------------------- 154 HRESULT STDMETHODCALLTYPE CPropertyHdl::GetCount( DWORD *pcProps ) 155 { 156 HRESULT hr = E_UNEXPECTED; 157 if ( m_pCache && pcProps ) 158 { 159 hr = m_pCache->GetCount( pcProps ); 160 } 161 162 return hr; 163 } 164 165 //----------------------------- 166 HRESULT STDMETHODCALLTYPE CPropertyHdl::GetAt( DWORD iProp, PROPERTYKEY *pKey ) 167 { 168 HRESULT hr = E_UNEXPECTED; 169 if ( m_pCache ) 170 { 171 hr = m_pCache->GetAt( iProp, pKey ); 172 } 173 174 return hr; 175 } 176 177 //----------------------------- 178 HRESULT STDMETHODCALLTYPE CPropertyHdl::GetValue( REFPROPERTYKEY key, PROPVARIANT *pPropVar ) 179 { 180 HRESULT hr = E_UNEXPECTED; 181 if ( m_pCache ) 182 { 183 hr = m_pCache->GetValue( key, pPropVar ); 184 } 185 186 return hr; 187 } 188 189 //----------------------------- 190 HRESULT STDMETHODCALLTYPE CPropertyHdl::SetValue( REFPROPERTYKEY key, REFPROPVARIANT propVar ) 191 { 192 HRESULT hr = E_UNEXPECTED; 193 if ( m_pCache ) 194 { 195 hr = STG_E_ACCESSDENIED; 196 } 197 return hr; 198 } 199 200 //----------------------------- 201 HRESULT STDMETHODCALLTYPE CPropertyHdl::Commit() 202 { 203 return S_OK; 204 } 205 206 //----------------------------- 207 // IPropertyStore 208 //----------------------------- 209 HRESULT STDMETHODCALLTYPE CPropertyHdl::IsPropertyWritable( REFPROPERTYKEY key ) 210 { 211 // We start with read only properties only 212 return S_FALSE; 213 } 214 215 //----------------------------- 216 // IInitializeWithStream 217 //----------------------------- 218 HRESULT STDMETHODCALLTYPE CPropertyHdl::Initialize( IStream *pStream, DWORD grfMode ) 219 { 220 if ( grfMode & STGM_READWRITE ) 221 return STG_E_ACCESSDENIED; 222 223 if ( !m_pCache ) 224 { 225 #ifdef __MINGW32__ 226 if ( FAILED( PSCreateMemoryPropertyStore( IID_IPropertyStoreCache, reinterpret_cast<void**>(&m_pCache) ) ) ) 227 #else 228 if ( FAILED( PSCreateMemoryPropertyStore( IID_PPV_ARGS( &m_pCache ) ) ) ) 229 #endif 230 OutputDebugStringFormat( "CPropertyHdl::Initialize: PSCreateMemoryPropertyStore failed" ); 231 232 zlib_filefunc_def z_filefunc; 233 pStream = PrepareIStream( pStream, z_filefunc ); 234 235 CMetaInfoReader *pMetaInfoReader = NULL; 236 237 try 238 { 239 pMetaInfoReader = new CMetaInfoReader( (void*)pStream, &z_filefunc ); 240 LoadProperties( pMetaInfoReader ); 241 delete pMetaInfoReader; 242 } 243 catch (const std::exception& e) 244 { 245 OutputDebugStringFormat( "CPropertyHdl::Initialize: Caught exception [%s]", e.what() ); 246 return E_FAIL; 247 } 248 /* 249 // load extended properties and search content 250 _LoadExtendedProperties(); 251 _LoadSearchContent(); 252 */ 253 } 254 255 return S_OK; 256 } 257 258 //----------------------------- 259 void CPropertyHdl::LoadProperties( CMetaInfoReader *pMetaInfoReader ) 260 { 261 OutputDebugStringFormat( "CPropertyHdl: LoadProperties\n" ); 262 PROPVARIANT propvarValues; 263 264 for ( UINT i = 0; i < (UINT)gPropertyMapTableSize; ++i ) 265 { 266 PropVariantClear( &propvarValues ); 267 HRESULT hr = GetItemData( pMetaInfoReader, i, &propvarValues); 268 if (hr == S_OK) 269 { 270 // coerce the value(s) to the appropriate type for the property key 271 hr = PSCoerceToCanonicalValue( g_rgPROPERTYMAP[i].key, &propvarValues ); 272 if (SUCCEEDED(hr)) 273 { 274 // cache the value(s) loaded 275 hr = m_pCache->SetValueAndState( g_rgPROPERTYMAP[i].key, &propvarValues, PSC_NORMAL ); 276 } 277 } 278 } 279 } 280 281 //----------------------------- 282 HRESULT CPropertyHdl::GetItemData( CMetaInfoReader *pMetaInfoReader, UINT nIndex, PROPVARIANT *pVarData ) 283 { 284 switch (nIndex) { 285 case 0: { 286 pVarData->vt = VT_BSTR; 287 pVarData->bstrVal = SysAllocString( pMetaInfoReader->getTagData( META_INFO_TITLE ).c_str() ); 288 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Title=%S.\n", pMetaInfoReader->getTagData( META_INFO_TITLE ).c_str() ); 289 return S_OK; 290 } 291 case 1: { 292 pVarData->vt = VT_BSTR; 293 pVarData->bstrVal = SysAllocString( pMetaInfoReader->getTagData( META_INFO_AUTHOR ).c_str() ); 294 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Author=%S.\n", pMetaInfoReader->getTagData( META_INFO_AUTHOR ).c_str() ); 295 return S_OK; 296 } 297 case 2: { 298 pVarData->vt = VT_BSTR; 299 pVarData->bstrVal = SysAllocString( pMetaInfoReader->getTagData( META_INFO_SUBJECT ).c_str() ); 300 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Subject=%S.\n", pMetaInfoReader->getTagData( META_INFO_SUBJECT ).c_str() ); 301 return S_OK; 302 } 303 case 3: { 304 pVarData->vt = VT_BSTR; 305 pVarData->bstrVal = SysAllocString( pMetaInfoReader->getTagData( META_INFO_KEYWORDS ).c_str() ); 306 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Keywords=%S.\n", pMetaInfoReader->getTagData( META_INFO_KEYWORDS ).c_str() ); 307 return S_OK; 308 } 309 case 4: { 310 pVarData->vt = VT_BSTR; 311 pVarData->bstrVal = SysAllocString( pMetaInfoReader->getTagData( META_INFO_DESCRIPTION ).c_str() ); 312 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Description=%S.\n", pMetaInfoReader->getTagData( META_INFO_DESCRIPTION ).c_str() ); 313 return S_OK; 314 } 315 case 5: { 316 pVarData->vt = VT_BSTR; 317 pVarData->bstrVal = SysAllocString( pMetaInfoReader->getTagAttribute( META_INFO_DOCUMENT_STATISTIC, META_INFO_PAGES ).c_str() ); 318 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Pages=%S.\n", pMetaInfoReader->getTagAttribute( META_INFO_DOCUMENT_STATISTIC, META_INFO_PAGES ).c_str() ); 319 return S_OK; 320 } 321 } 322 323 return S_FALSE; 324 } 325 326 //----------------------------------------------------------------------------- 327 // CClassFactory 328 //----------------------------------------------------------------------------- 329 330 long CClassFactory::s_ServerLocks = 0; 331 332 //----------------------------------------------------------------------------- 333 CClassFactory::CClassFactory( const CLSID& clsid ) : 334 m_RefCnt(1), 335 m_Clsid(clsid) 336 { 337 InterlockedIncrement( &g_DllRefCnt ); 338 } 339 340 //----------------------------------------------------------------------------- 341 CClassFactory::~CClassFactory() 342 { 343 InterlockedDecrement( &g_DllRefCnt ); 344 } 345 346 //----------------------------------------------------------------------------- 347 // IUnknown methods 348 //----------------------------------------------------------------------------- 349 HRESULT STDMETHODCALLTYPE CClassFactory::QueryInterface( REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject ) 350 { 351 *ppvObject = 0; 352 353 if ( IID_IUnknown == riid || IID_IClassFactory == riid ) 354 { 355 IUnknown* pUnk = this; 356 pUnk->AddRef(); 357 *ppvObject = pUnk; 358 return S_OK; 359 } 360 361 return E_NOINTERFACE; 362 } 363 364 //----------------------------------------------------------------------------- 365 ULONG STDMETHODCALLTYPE CClassFactory::AddRef( void ) 366 { 367 return InterlockedIncrement( &m_RefCnt ); 368 } 369 370 //----------------------------------------------------------------------------- 371 ULONG STDMETHODCALLTYPE CClassFactory::Release( void ) 372 { 373 long refcnt = InterlockedDecrement( &m_RefCnt ); 374 375 if (0 == refcnt) 376 delete this; 377 378 return refcnt; 379 } 380 381 //----------------------------------------------------------------------------- 382 // IClassFactory methods 383 //----------------------------------------------------------------------------- 384 HRESULT STDMETHODCALLTYPE CClassFactory::CreateInstance( 385 IUnknown __RPC_FAR *pUnkOuter, 386 REFIID riid, 387 void __RPC_FAR *__RPC_FAR *ppvObject) 388 { 389 if ( pUnkOuter != NULL ) 390 return CLASS_E_NOAGGREGATION; 391 392 IUnknown* pUnk = 0; 393 394 if ( CLSID_PROPERTY_HANDLER == m_Clsid ) 395 pUnk = static_cast<IPropertyStore*>( new CPropertyHdl() ); 396 397 POST_CONDITION(pUnk != 0, "Could not create COM object"); 398 399 if (0 == pUnk) 400 return E_OUTOFMEMORY; 401 402 HRESULT hr = pUnk->QueryInterface( riid, ppvObject ); 403 404 // if QueryInterface failed the component will destroy itself 405 pUnk->Release(); 406 407 return hr; 408 } 409 410 //----------------------------------------------------------------------------- 411 HRESULT STDMETHODCALLTYPE CClassFactory::LockServer( BOOL fLock ) 412 { 413 if ( fLock ) 414 InterlockedIncrement( &s_ServerLocks ); 415 else 416 InterlockedDecrement( &s_ServerLocks ); 417 418 return S_OK; 419 } 420 421 //----------------------------------------------------------------------------- 422 bool CClassFactory::IsLocked() 423 { 424 return ( s_ServerLocks > 0 ); 425 } 426 427 //----------------------------------------------------------------------------- 428 extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv) 429 { 430 OutputDebugStringFormat( "DllGetClassObject.\n" ); 431 *ppv = 0; 432 433 if ( rclsid != CLSID_PROPERTY_HANDLER ) 434 return CLASS_E_CLASSNOTAVAILABLE; 435 436 if ( (riid != IID_IUnknown) && (riid != IID_IClassFactory) ) 437 return E_NOINTERFACE; 438 439 IUnknown* pUnk = new CClassFactory( rclsid ); 440 if ( 0 == pUnk ) 441 return E_OUTOFMEMORY; 442 443 *ppv = pUnk; 444 return S_OK; 445 } 446 447 //----------------------------------------------------------------------------- 448 extern "C" STDAPI DllCanUnloadNow( void ) 449 { 450 OutputDebugStringFormat( "DllCanUnloadNow.\n" ); 451 if (CClassFactory::IsLocked() || g_DllRefCnt > 0) 452 return S_FALSE; 453 454 return S_OK; 455 } 456 457 //----------------------------------------------------------------------------- 458 BOOL WINAPI DllMain( HINSTANCE hInst, ULONG /*ul_reason_for_call*/, LPVOID /*lpReserved*/ ) 459 { 460 OutputDebugStringFormat( "DllMain.\n" ); 461 g_hModule = hInst; 462 return TRUE; 463 } 464