1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "internal/global.hxx"
21 #include "internal/propertyhdl.hxx"
22 #include "internal/fileextensions.hxx"
23 #include "internal/metainforeader.hxx"
24 #include "internal/utilities.hxx"
25 #include "internal/config.hxx"
28 #include <propvarutil.h>
29 #include <sal/macros.h>
34 #include "internal/stream_helper.hxx"
40 HINSTANCE g_hModule
= NULL
;
42 // Map of property keys to the locations of their value(s) in the .??? XML schema
46 PCWSTR pszXPathParent
;
47 PCWSTR pszValueNodeName
;
50 PROPERTYMAP g_rgPROPERTYMAP
[] =
52 { PKEY_Title
, L
"LibreOffice", L
"Title" },
53 { PKEY_Author
, L
"LibreOffice", L
"Author" },
54 { PKEY_Subject
, L
"LibreOffice", L
"Subject" },
55 { PKEY_Keywords
, L
"LibreOffice", L
"Keyword" },
56 { PKEY_Comment
, L
"LibreOffice", L
"Comments" },
59 size_t gPropertyMapTableSize
= sizeof(g_rgPROPERTYMAP
)/sizeof(g_rgPROPERTYMAP
[0]);
63 CPropertyHdl::CPropertyHdl( long nRefCnt
) :
67 OutputDebugStringFormat( "CPropertyHdl: CTOR\n" );
68 InterlockedIncrement( &g_DllRefCnt
);
73 CPropertyHdl::~CPropertyHdl()
80 InterlockedDecrement( &g_DllRefCnt
);
86 HRESULT STDMETHODCALLTYPE
CPropertyHdl::QueryInterface(REFIID riid
, void __RPC_FAR
*__RPC_FAR
*ppvObject
)
90 if (IID_IUnknown
== riid
|| IID_IPropertyStore
== riid
)
92 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (IID_IPropertyStore)\n" );
93 IUnknown
* pUnk
= static_cast<IPropertyStore
*>(this);
98 else if (IID_IPropertyStoreCapabilities
== riid
)
100 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (IID_IPropertyStoreCapabilities)\n" );
101 IUnknown
* pUnk
= static_cast<IPropertyStore
*>(this);
106 else if (IID_IInitializeWithStream
== riid
)
108 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (IID_IInitializeWithStream)\n" );
109 IUnknown
* pUnk
= static_cast<IInitializeWithStream
*>(this);
114 OutputDebugStringFormat( "CPropertyHdl: QueryInterface (something different)\n" );
116 return E_NOINTERFACE
;
120 ULONG STDMETHODCALLTYPE
CPropertyHdl::AddRef()
122 return InterlockedIncrement( &m_RefCnt
);
126 ULONG STDMETHODCALLTYPE
CPropertyHdl::Release()
128 long refcnt
= InterlockedDecrement( &m_RefCnt
);
139 HRESULT STDMETHODCALLTYPE
CPropertyHdl::GetCount( DWORD
*pcProps
)
141 HRESULT hr
= E_UNEXPECTED
;
142 if ( m_pCache
&& pcProps
)
144 hr
= m_pCache
->GetCount( pcProps
);
151 HRESULT STDMETHODCALLTYPE
CPropertyHdl::GetAt( DWORD iProp
, PROPERTYKEY
*pKey
)
153 HRESULT hr
= E_UNEXPECTED
;
156 hr
= m_pCache
->GetAt( iProp
, pKey
);
163 HRESULT STDMETHODCALLTYPE
CPropertyHdl::GetValue( REFPROPERTYKEY key
, PROPVARIANT
*pPropVar
)
165 HRESULT hr
= E_UNEXPECTED
;
168 hr
= m_pCache
->GetValue( key
, pPropVar
);
175 HRESULT STDMETHODCALLTYPE
176 CPropertyHdl::SetValue(REFPROPERTYKEY
/*key*/, REFPROPVARIANT
/*propVar*/)
178 HRESULT hr
= E_UNEXPECTED
;
181 hr
= STG_E_ACCESSDENIED
;
187 HRESULT STDMETHODCALLTYPE
CPropertyHdl::Commit()
195 HRESULT STDMETHODCALLTYPE
196 CPropertyHdl::IsPropertyWritable(REFPROPERTYKEY
/*key*/)
198 // We start with read only properties only
203 // IInitializeWithStream
205 HRESULT STDMETHODCALLTYPE
CPropertyHdl::Initialize( IStream
*pStream
, DWORD grfMode
)
207 if ( grfMode
& STGM_READWRITE
)
208 return STG_E_ACCESSDENIED
;
213 if ( FAILED( PSCreateMemoryPropertyStore( IID_IPropertyStoreCache
, reinterpret_cast<void**>(&m_pCache
) ) ) )
215 if ( FAILED( PSCreateMemoryPropertyStore( IID_PPV_ARGS( &m_pCache
) ) ) )
217 OutputDebugStringFormat( "CPropertyHdl::Initialize: PSCreateMemoryPropertyStore failed" );
219 BufferStream
tmpStream(pStream
);
221 CMetaInfoReader
*pMetaInfoReader
= NULL
;
225 pMetaInfoReader
= new CMetaInfoReader( &tmpStream
);
226 LoadProperties( pMetaInfoReader
);
227 delete pMetaInfoReader
;
229 catch (const std::exception
& e
)
231 OutputDebugStringFormat( "CPropertyHdl::Initialize: Caught exception [%s]", e
.what() );
240 void CPropertyHdl::LoadProperties( CMetaInfoReader
*pMetaInfoReader
)
242 OutputDebugStringFormat( "CPropertyHdl: LoadProperties\n" );
243 PROPVARIANT propvarValues
;
245 for ( UINT i
= 0; i
< (UINT
)gPropertyMapTableSize
; ++i
)
247 PropVariantClear( &propvarValues
);
248 HRESULT hr
= GetItemData( pMetaInfoReader
, i
, &propvarValues
);
251 // coerce the value(s) to the appropriate type for the property key
252 hr
= PSCoerceToCanonicalValue( g_rgPROPERTYMAP
[i
].key
, &propvarValues
);
255 // cache the value(s) loaded
256 hr
= m_pCache
->SetValueAndState( g_rgPROPERTYMAP
[i
].key
, &propvarValues
, PSC_NORMAL
);
263 HRESULT
CPropertyHdl::GetItemData( CMetaInfoReader
*pMetaInfoReader
, UINT nIndex
, PROPVARIANT
*pVarData
)
267 pVarData
->vt
= VT_BSTR
;
268 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_TITLE
).c_str() );
269 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Title=%S.\n", pMetaInfoReader
->getTagData( META_INFO_TITLE
).c_str() );
273 pVarData
->vt
= VT_BSTR
;
274 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_AUTHOR
).c_str() );
275 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Author=%S.\n", pMetaInfoReader
->getTagData( META_INFO_AUTHOR
).c_str() );
279 pVarData
->vt
= VT_BSTR
;
280 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_SUBJECT
).c_str() );
281 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Subject=%S.\n", pMetaInfoReader
->getTagData( META_INFO_SUBJECT
).c_str() );
285 pVarData
->vt
= VT_BSTR
;
286 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_KEYWORDS
).c_str() );
287 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Keywords=%S.\n", pMetaInfoReader
->getTagData( META_INFO_KEYWORDS
).c_str() );
291 pVarData
->vt
= VT_BSTR
;
292 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_DESCRIPTION
).c_str() );
293 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Description=%S.\n", pMetaInfoReader
->getTagData( META_INFO_DESCRIPTION
).c_str() );
297 pVarData
->vt
= VT_BSTR
;
298 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagAttribute( META_INFO_DOCUMENT_STATISTIC
, META_INFO_PAGES
).c_str() );
299 OutputDebugStringFormat( "CPropertyHdl::GetItemData: Pages=%S.\n", pMetaInfoReader
->getTagAttribute( META_INFO_DOCUMENT_STATISTIC
, META_INFO_PAGES
).c_str() );
311 long CClassFactory::s_ServerLocks
= 0;
314 CClassFactory::CClassFactory( const CLSID
& clsid
) :
318 InterlockedIncrement( &g_DllRefCnt
);
322 CClassFactory::~CClassFactory()
324 InterlockedDecrement( &g_DllRefCnt
);
330 HRESULT STDMETHODCALLTYPE
CClassFactory::QueryInterface( REFIID riid
, void __RPC_FAR
*__RPC_FAR
*ppvObject
)
334 if ( IID_IUnknown
== riid
|| IID_IClassFactory
== riid
)
336 IUnknown
* pUnk
= this;
342 return E_NOINTERFACE
;
346 ULONG STDMETHODCALLTYPE
CClassFactory::AddRef()
348 return InterlockedIncrement( &m_RefCnt
);
352 ULONG STDMETHODCALLTYPE
CClassFactory::Release()
354 long refcnt
= InterlockedDecrement( &m_RefCnt
);
363 // IClassFactory methods
365 HRESULT STDMETHODCALLTYPE
CClassFactory::CreateInstance(
366 IUnknown __RPC_FAR
*pUnkOuter
,
368 void __RPC_FAR
*__RPC_FAR
*ppvObject
)
370 if ( pUnkOuter
!= NULL
)
371 return CLASS_E_NOAGGREGATION
;
375 if ( CLSID_PROPERTY_HANDLER
== m_Clsid
)
376 pUnk
= static_cast<IPropertyStore
*>( new CPropertyHdl() );
380 return E_OUTOFMEMORY
;
383 HRESULT hr
= pUnk
->QueryInterface( riid
, ppvObject
);
385 // if QueryInterface failed the component will destroy itself
392 HRESULT STDMETHODCALLTYPE
CClassFactory::LockServer( BOOL fLock
)
395 InterlockedIncrement( &s_ServerLocks
);
397 InterlockedDecrement( &s_ServerLocks
);
403 bool CClassFactory::IsLocked()
405 return ( s_ServerLocks
> 0 );
409 extern "C" STDAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void** ppv
)
411 OutputDebugStringFormat( "DllGetClassObject.\n" );
414 if ( rclsid
!= CLSID_PROPERTY_HANDLER
)
415 return CLASS_E_CLASSNOTAVAILABLE
;
417 if ( (riid
!= IID_IUnknown
) && (riid
!= IID_IClassFactory
) )
418 return E_NOINTERFACE
;
420 IUnknown
* pUnk
= new CClassFactory( rclsid
);
426 extern "C" STDAPI
DllCanUnloadNow()
428 OutputDebugStringFormat( "DllCanUnloadNow.\n" );
429 if (CClassFactory::IsLocked() || g_DllRefCnt
> 0)
436 BOOL WINAPI
DllMain( HINSTANCE hInst
, ULONG
/*ul_reason_for_call*/, LPVOID
/*lpReserved*/ )
438 OutputDebugStringFormat( "DllMain.\n" );
443 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */