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 .
21 #include <propertyhdl.hxx>
22 #include <fileextensions.hxx>
23 #include <metainforeader.hxx>
24 #include <utilities.hxx>
28 #include <propvarutil.h>
29 #include <sal/macros.h>
34 #include <stream_helper.hxx>
40 static HINSTANCE g_hModule
= nullptr;
42 const PROPERTYKEY g_rgPROPERTIES
[] =
51 size_t const gPropertyTableSize
= SAL_N_ELEMENTS(g_rgPROPERTIES
);
54 CPropertyHdl::CPropertyHdl( LONG nRefCnt
) :
58 OutputDebugStringFormatW( L
"CPropertyHdl: CTOR\n" );
59 InterlockedIncrement( &g_DllRefCnt
);
63 CPropertyHdl::~CPropertyHdl()
70 InterlockedDecrement( &g_DllRefCnt
);
76 HRESULT STDMETHODCALLTYPE
CPropertyHdl::QueryInterface(REFIID riid
, void __RPC_FAR
*__RPC_FAR
*ppvObject
)
80 if (IID_IUnknown
== riid
|| IID_IPropertyStore
== riid
)
82 OutputDebugStringFormatW( L
"CPropertyHdl: QueryInterface (IID_IPropertyStore)\n" );
83 IUnknown
* pUnk
= static_cast<IPropertyStore
*>(this);
88 else if (IID_IPropertyStoreCapabilities
== riid
)
90 OutputDebugStringFormatW( L
"CPropertyHdl: QueryInterface (IID_IPropertyStoreCapabilities)\n" );
91 IUnknown
* pUnk
= static_cast<IPropertyStore
*>(this);
96 else if (IID_IInitializeWithStream
== riid
)
98 OutputDebugStringFormatW( L
"CPropertyHdl: QueryInterface (IID_IInitializeWithStream)\n" );
99 IUnknown
* pUnk
= static_cast<IInitializeWithStream
*>(this);
104 OutputDebugStringFormatW( L
"CPropertyHdl: QueryInterface (something different)\n" );
106 return E_NOINTERFACE
;
110 ULONG STDMETHODCALLTYPE
CPropertyHdl::AddRef()
112 return InterlockedIncrement( &m_RefCnt
);
116 ULONG STDMETHODCALLTYPE
CPropertyHdl::Release()
118 LONG refcnt
= InterlockedDecrement( &m_RefCnt
);
129 HRESULT STDMETHODCALLTYPE
CPropertyHdl::GetCount( DWORD
*pcProps
)
131 HRESULT hr
= E_UNEXPECTED
;
132 if ( m_pCache
&& pcProps
)
134 hr
= m_pCache
->GetCount( pcProps
);
141 HRESULT STDMETHODCALLTYPE
CPropertyHdl::GetAt( DWORD iProp
, PROPERTYKEY
*pKey
)
143 HRESULT hr
= E_UNEXPECTED
;
146 hr
= m_pCache
->GetAt( iProp
, pKey
);
153 HRESULT STDMETHODCALLTYPE
CPropertyHdl::GetValue( REFPROPERTYKEY key
, PROPVARIANT
*pPropVar
)
155 HRESULT hr
= E_UNEXPECTED
;
158 hr
= m_pCache
->GetValue( key
, pPropVar
);
165 HRESULT STDMETHODCALLTYPE
166 CPropertyHdl::SetValue(REFPROPERTYKEY
/*key*/, REFPROPVARIANT
/*propVar*/)
168 HRESULT hr
= E_UNEXPECTED
;
171 hr
= STG_E_ACCESSDENIED
;
177 HRESULT STDMETHODCALLTYPE
CPropertyHdl::Commit()
185 HRESULT STDMETHODCALLTYPE
186 CPropertyHdl::IsPropertyWritable(REFPROPERTYKEY
/*key*/)
188 // We start with read only properties only
193 // IInitializeWithStream
195 HRESULT STDMETHODCALLTYPE
CPropertyHdl::Initialize( IStream
*pStream
, DWORD grfMode
)
197 if ( grfMode
& STGM_READWRITE
)
198 return STG_E_ACCESSDENIED
;
202 if ( FAILED( PSCreateMemoryPropertyStore( IID_PPV_ARGS( &m_pCache
) ) ) )
203 OutputDebugStringFormatW( L
"CPropertyHdl::Initialize: PSCreateMemoryPropertyStore failed" );
205 BufferStream
tmpStream(pStream
);
207 CMetaInfoReader
*pMetaInfoReader
= nullptr;
211 pMetaInfoReader
= new CMetaInfoReader( &tmpStream
);
212 LoadProperties( pMetaInfoReader
);
213 delete pMetaInfoReader
;
215 catch (const std::exception
& e
)
217 // To output 8-bit string using unicode version of formatting functions, use capital %S type
218 // see https://msdn.microsoft.com/en-us/library/hf4y5e3w
219 OutputDebugStringFormatW( L
"CPropertyHdl::Initialize: Caught exception [%S]", e
.what() );
229 HRESULT
GetItemData( CMetaInfoReader
*pMetaInfoReader
, UINT nIndex
, PROPVARIANT
*pVarData
)
233 pVarData
->vt
= VT_BSTR
;
234 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_TITLE
).c_str() );
235 OutputDebugStringFormatW( L
"CPropertyHdl::GetItemData: Title=%s.\n", pMetaInfoReader
->getTagData( META_INFO_TITLE
).c_str() );
239 pVarData
->vt
= VT_BSTR
;
240 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_AUTHOR
).c_str() );
241 OutputDebugStringFormatW( L
"CPropertyHdl::GetItemData: Author=%s.\n", pMetaInfoReader
->getTagData( META_INFO_AUTHOR
).c_str() );
245 pVarData
->vt
= VT_BSTR
;
246 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_SUBJECT
).c_str() );
247 OutputDebugStringFormatW( L
"CPropertyHdl::GetItemData: Subject=%s.\n", pMetaInfoReader
->getTagData( META_INFO_SUBJECT
).c_str() );
251 pVarData
->vt
= VT_BSTR
;
252 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_KEYWORDS
).c_str() );
253 OutputDebugStringFormatW( L
"CPropertyHdl::GetItemData: Keywords=%s.\n", pMetaInfoReader
->getTagData( META_INFO_KEYWORDS
).c_str() );
257 pVarData
->vt
= VT_BSTR
;
258 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagData( META_INFO_DESCRIPTION
).c_str() );
259 OutputDebugStringFormatW( L
"CPropertyHdl::GetItemData: Description=%s.\n", pMetaInfoReader
->getTagData( META_INFO_DESCRIPTION
).c_str() );
263 pVarData
->vt
= VT_BSTR
;
264 pVarData
->bstrVal
= SysAllocString( pMetaInfoReader
->getTagAttribute( META_INFO_DOCUMENT_STATISTIC
, META_INFO_PAGES
).c_str() );
265 OutputDebugStringFormatW( L
"CPropertyHdl::GetItemData: Pages=%s.\n", pMetaInfoReader
->getTagAttribute( META_INFO_DOCUMENT_STATISTIC
, META_INFO_PAGES
).c_str() );
275 void CPropertyHdl::LoadProperties( CMetaInfoReader
*pMetaInfoReader
)
277 OutputDebugStringFormatW( L
"CPropertyHdl: LoadProperties\n" );
278 PROPVARIANT propvarValues
;
280 for ( UINT i
= 0; i
< UINT(gPropertyTableSize
); ++i
)
282 PropVariantClear( &propvarValues
);
283 HRESULT hr
= GetItemData( pMetaInfoReader
, i
, &propvarValues
);
286 // coerce the value(s) to the appropriate type for the property key
287 hr
= PSCoerceToCanonicalValue( g_rgPROPERTIES
[i
], &propvarValues
);
290 // cache the value(s) loaded
291 hr
= m_pCache
->SetValueAndState( g_rgPROPERTIES
[i
], &propvarValues
, PSC_NORMAL
);
300 LONG
CClassFactory::s_ServerLocks
= 0;
303 CClassFactory::CClassFactory( const CLSID
& clsid
) :
307 InterlockedIncrement( &g_DllRefCnt
);
311 CClassFactory::~CClassFactory()
313 InterlockedDecrement( &g_DllRefCnt
);
319 HRESULT STDMETHODCALLTYPE
CClassFactory::QueryInterface( REFIID riid
, void __RPC_FAR
*__RPC_FAR
*ppvObject
)
321 *ppvObject
= nullptr;
323 if ( IID_IUnknown
== riid
|| IID_IClassFactory
== riid
)
325 IUnknown
* pUnk
= this;
331 return E_NOINTERFACE
;
335 ULONG STDMETHODCALLTYPE
CClassFactory::AddRef()
337 return InterlockedIncrement( &m_RefCnt
);
341 ULONG STDMETHODCALLTYPE
CClassFactory::Release()
343 LONG refcnt
= InterlockedDecrement( &m_RefCnt
);
352 // IClassFactory methods
354 HRESULT STDMETHODCALLTYPE
CClassFactory::CreateInstance(
355 IUnknown __RPC_FAR
*pUnkOuter
,
357 void __RPC_FAR
*__RPC_FAR
*ppvObject
)
359 if ( pUnkOuter
!= nullptr )
360 return CLASS_E_NOAGGREGATION
;
362 IUnknown
* pUnk
= nullptr;
364 if ( CLSID_PROPERTY_HANDLER
== m_Clsid
)
365 pUnk
= static_cast<IPropertyStore
*>( new CPropertyHdl() );
369 return E_OUTOFMEMORY
;
372 HRESULT hr
= pUnk
->QueryInterface( riid
, ppvObject
);
374 // if QueryInterface failed the component will destroy itself
381 HRESULT STDMETHODCALLTYPE
CClassFactory::LockServer( BOOL fLock
)
384 InterlockedIncrement( &s_ServerLocks
);
386 InterlockedDecrement( &s_ServerLocks
);
392 bool CClassFactory::IsLocked()
394 return ( s_ServerLocks
> 0 );
398 STDAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
)
400 OutputDebugStringFormatW( L
"DllGetClassObject.\n" );
403 if ( rclsid
!= CLSID_PROPERTY_HANDLER
)
404 return CLASS_E_CLASSNOTAVAILABLE
;
406 if ( (riid
!= IID_IUnknown
) && (riid
!= IID_IClassFactory
) )
407 return E_NOINTERFACE
;
409 IUnknown
* pUnk
= new CClassFactory( rclsid
);
415 STDAPI
DllCanUnloadNow()
417 OutputDebugStringFormatW( L
"DllCanUnloadNow.\n" );
418 if (CClassFactory::IsLocked() || g_DllRefCnt
> 0)
425 BOOL WINAPI
DllMain( HINSTANCE hInst
, ULONG
/*ul_reason_for_call*/, LPVOID
/*lpReserved*/ )
427 OutputDebugStringFormatW( L
"DllMain.\n" );
432 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */