LibreOffice Module shell (master) 1
propertyhdl.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <global.hxx>
21#include <propertyhdl.hxx>
22#include <fileextensions.hxx>
23#include <metainforeader.hxx>
24#include <utilities.hxx>
25#include <config.hxx>
26
27#include <propkey.h>
28#include <propvarutil.h>
29#include <sal/macros.h>
30
31#include <malloc.h>
32#include <strsafe.h>
33
34#include <stream_helper.hxx>
35
36
37// Module global
38
40static HINSTANCE g_hModule = nullptr;
41
42const PROPERTYKEY g_rgPROPERTIES[] =
43{
44 PKEY_Title,
45 PKEY_Author,
46 PKEY_Subject,
47 PKEY_Keywords,
48 PKEY_Comment
49};
50
52
53
55 m_RefCnt( nRefCnt ),
56 m_pCache( nullptr )
57{
58 OutputDebugStringFormatW( L"CPropertyHdl: CTOR\n" );
59 InterlockedIncrement( &g_DllRefCnt );
60}
61
62
64{
65 if ( m_pCache )
66 {
67 m_pCache->Release();
68 m_pCache = nullptr;
69 }
70 InterlockedDecrement( &g_DllRefCnt );
71}
72
73
74// IUnknown methods
75
76HRESULT STDMETHODCALLTYPE CPropertyHdl::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
77{
78 *ppvObject = nullptr;
79
80 if (IID_IUnknown == riid || IID_IPropertyStore == riid)
81 {
82 OutputDebugStringFormatW( L"CPropertyHdl: QueryInterface (IID_IPropertyStore)\n" );
83 IUnknown* pUnk = static_cast<IPropertyStore*>(this);
84 pUnk->AddRef();
85 *ppvObject = pUnk;
86 return S_OK;
87 }
88 else if (IID_IPropertyStoreCapabilities == riid)
89 {
90 OutputDebugStringFormatW( L"CPropertyHdl: QueryInterface (IID_IPropertyStoreCapabilities)\n" );
91 IUnknown* pUnk = static_cast<IPropertyStore*>(this);
92 pUnk->AddRef();
93 *ppvObject = pUnk;
94 return S_OK;
95 }
96 else if (IID_IInitializeWithStream == riid)
97 {
98 OutputDebugStringFormatW( L"CPropertyHdl: QueryInterface (IID_IInitializeWithStream)\n" );
99 IUnknown* pUnk = static_cast<IInitializeWithStream*>(this);
100 pUnk->AddRef();
101 *ppvObject = pUnk;
102 return S_OK;
103 }
104 OutputDebugStringFormatW( L"CPropertyHdl: QueryInterface (something different)\n" );
105
106 return E_NOINTERFACE;
107}
108
109
110ULONG STDMETHODCALLTYPE CPropertyHdl::AddRef()
111{
112 return InterlockedIncrement( &m_RefCnt );
113}
114
115
116ULONG STDMETHODCALLTYPE CPropertyHdl::Release()
117{
118 LONG refcnt = InterlockedDecrement( &m_RefCnt );
119
120 if ( 0 == m_RefCnt )
121 delete this;
122
123 return refcnt;
124}
125
126
127// IPropertyStore
128
129HRESULT STDMETHODCALLTYPE CPropertyHdl::GetCount( DWORD *pcProps )
130{
131 HRESULT hr = E_UNEXPECTED;
132 if ( m_pCache && pcProps )
133 {
134 hr = m_pCache->GetCount( pcProps );
135 }
136
137 return hr;
138}
139
140
141HRESULT STDMETHODCALLTYPE CPropertyHdl::GetAt( DWORD iProp, PROPERTYKEY *pKey )
142{
143 HRESULT hr = E_UNEXPECTED;
144 if ( m_pCache )
145 {
146 hr = m_pCache->GetAt( iProp, pKey );
147 }
148
149 return hr;
150}
151
152
153HRESULT STDMETHODCALLTYPE CPropertyHdl::GetValue( REFPROPERTYKEY key, PROPVARIANT *pPropVar )
154{
155 HRESULT hr = E_UNEXPECTED;
156 if ( m_pCache )
157 {
158 hr = m_pCache->GetValue( key, pPropVar );
159 }
160
161 return hr;
162}
163
164
165HRESULT STDMETHODCALLTYPE
166CPropertyHdl::SetValue(REFPROPERTYKEY /*key*/, REFPROPVARIANT /*propVar*/)
167{
168 HRESULT hr = E_UNEXPECTED;
169 if ( m_pCache )
170 {
171 hr = STG_E_ACCESSDENIED;
172 }
173 return hr;
174}
175
176
177HRESULT STDMETHODCALLTYPE CPropertyHdl::Commit()
178{
179 return S_OK;
180}
181
182
183// IPropertyStore
184
185HRESULT STDMETHODCALLTYPE
186CPropertyHdl::IsPropertyWritable(REFPROPERTYKEY /*key*/)
187{
188 // We start with read only properties only
189 return S_FALSE;
190}
191
192
193// IInitializeWithStream
194
195HRESULT STDMETHODCALLTYPE CPropertyHdl::Initialize( IStream *pStream, DWORD grfMode )
196{
197 if ( grfMode & STGM_READWRITE )
198 return STG_E_ACCESSDENIED;
199
200 if ( !m_pCache )
201 {
202 if ( FAILED( PSCreateMemoryPropertyStore( IID_PPV_ARGS( &m_pCache ) ) ) )
203 OutputDebugStringFormatW( L"CPropertyHdl::Initialize: PSCreateMemoryPropertyStore failed" );
204
205 BufferStream tmpStream(pStream);
206
207 CMetaInfoReader *pMetaInfoReader = nullptr;
208
209 try
210 {
211 pMetaInfoReader = new CMetaInfoReader( &tmpStream );
212 LoadProperties( pMetaInfoReader );
213 delete pMetaInfoReader;
214 }
215 catch (const std::exception& e)
216 {
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() );
220 return E_FAIL;
221 }
222 }
223
224 return S_OK;
225}
226
227namespace {
228
229HRESULT GetItemData( CMetaInfoReader *pMetaInfoReader, UINT nIndex, PROPVARIANT *pVarData )
230{
231 switch (nIndex) {
232 case 0: {
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() );
236 return S_OK;
237 }
238 case 1: {
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() );
242 return S_OK;
243 }
244 case 2: {
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() );
248 return S_OK;
249 }
250 case 3: {
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() );
254 return S_OK;
255 }
256 case 4: {
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() );
260 return S_OK;
261 }
262 case 5: {
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() );
266 return S_OK;
267 }
268 }
269
270 return S_FALSE;
271}
272
273}
274
276{
277 OutputDebugStringFormatW( L"CPropertyHdl: LoadProperties\n" );
278 PROPVARIANT propvarValues;
279
280 for ( UINT i = 0; i < UINT(gPropertyTableSize); ++i )
281 {
282 PropVariantClear( &propvarValues );
283 HRESULT hr = GetItemData( pMetaInfoReader, i, &propvarValues);
284 if (hr == S_OK)
285 {
286 // coerce the value(s) to the appropriate type for the property key
287 hr = PSCoerceToCanonicalValue( g_rgPROPERTIES[i], &propvarValues );
288 if (SUCCEEDED(hr))
289 {
290 // cache the value(s) loaded
291 hr = m_pCache->SetValueAndState( g_rgPROPERTIES[i], &propvarValues, PSC_NORMAL );
292 }
293 }
294 }
295}
296
297// CClassFactory
298
299
301
302
303CClassFactory::CClassFactory( const CLSID& clsid ) :
304 m_RefCnt(1),
305 m_Clsid(clsid)
306{
307 InterlockedIncrement( &g_DllRefCnt );
308}
309
310
312{
313 InterlockedDecrement( &g_DllRefCnt );
314}
315
316
317// IUnknown methods
318
319HRESULT STDMETHODCALLTYPE CClassFactory::QueryInterface( REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject )
320{
321 *ppvObject = nullptr;
322
323 if ( IID_IUnknown == riid || IID_IClassFactory == riid )
324 {
325 IUnknown* pUnk = this;
326 pUnk->AddRef();
327 *ppvObject = pUnk;
328 return S_OK;
329 }
330
331 return E_NOINTERFACE;
332}
333
334
335ULONG STDMETHODCALLTYPE CClassFactory::AddRef()
336{
337 return InterlockedIncrement( &m_RefCnt );
338}
339
340
341ULONG STDMETHODCALLTYPE CClassFactory::Release()
342{
343 LONG refcnt = InterlockedDecrement( &m_RefCnt );
344
345 if (0 == refcnt)
346 delete this;
347
348 return refcnt;
349}
350
351
352// IClassFactory methods
353
354HRESULT STDMETHODCALLTYPE CClassFactory::CreateInstance(
355 IUnknown __RPC_FAR *pUnkOuter,
356 REFIID riid,
357 void __RPC_FAR *__RPC_FAR *ppvObject)
358{
359 if ( pUnkOuter != nullptr )
360 return CLASS_E_NOAGGREGATION;
361
362 IUnknown* pUnk = nullptr;
363
365 pUnk = static_cast<IPropertyStore*>( new CPropertyHdl() );
366
367 if (nullptr == pUnk)
368 {
369 return E_OUTOFMEMORY;
370 }
371
372 HRESULT hr = pUnk->QueryInterface( riid, ppvObject );
373
374 // if QueryInterface failed the component will destroy itself
375 pUnk->Release();
376
377 return hr;
378}
379
380
381HRESULT STDMETHODCALLTYPE CClassFactory::LockServer( BOOL fLock )
382{
383 if ( fLock )
384 InterlockedIncrement( &s_ServerLocks );
385 else
386 InterlockedDecrement( &s_ServerLocks );
387
388 return S_OK;
389}
390
391
393{
394 return ( s_ServerLocks > 0 );
395}
396
397
398STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
399{
400 OutputDebugStringFormatW( L"DllGetClassObject.\n" );
401 *ppv = nullptr;
402
403 if ( rclsid != CLSID_PROPERTY_HANDLER )
404 return CLASS_E_CLASSNOTAVAILABLE;
405
406 if ( (riid != IID_IUnknown) && (riid != IID_IClassFactory) )
407 return E_NOINTERFACE;
408
409 IUnknown* pUnk = new CClassFactory( rclsid );
410 *ppv = pUnk;
411 return S_OK;
412}
413
414
416{
417 OutputDebugStringFormatW( L"DllCanUnloadNow.\n" );
419 return S_FALSE;
420
421 return S_OK;
422}
423
424
425BOOL WINAPI DllMain( HINSTANCE hInst, ULONG /*ul_reason_for_call*/, LPVOID /*lpReserved*/ )
426{
427 OutputDebugStringFormatW( L"DllMain.\n" );
428 g_hModule = hInst;
429 return TRUE;
430}
431
432/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override
virtual HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown __RPC_FAR *pUnkOuter, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override
virtual ULONG STDMETHODCALLTYPE Release() override
virtual ULONG STDMETHODCALLTYPE AddRef() override
CClassFactory(const CLSID &clsid)
virtual ~CClassFactory()
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override
static LONG s_ServerLocks
static bool IsLocked()
std::wstring getTagData(const std::wstring &TagName)
Get a specific tag content, compound tags will be returned as comma separated list.
std::wstring getTagAttribute(const std::wstring &TagName, const std::wstring &AttributeName)
Get a specific attribute content.
virtual HRESULT STDMETHODCALLTYPE SetValue(REFPROPERTYKEY key, REFPROPVARIANT propVar) override
virtual HRESULT STDMETHODCALLTYPE GetCount(DWORD *pcProps) override
void LoadProperties(CMetaInfoReader *pMetaInfoReader)
virtual HRESULT STDMETHODCALLTYPE GetValue(REFPROPERTYKEY key, PROPVARIANT *pPropVar) override
virtual HRESULT STDMETHODCALLTYPE IsPropertyWritable(REFPROPERTYKEY key) override
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override
Definition: propertyhdl.cxx:76
virtual HRESULT STDMETHODCALLTYPE Commit() override
CPropertyHdl(LONG RefCnt=1)
Definition: propertyhdl.cxx:54
virtual ~CPropertyHdl()
Definition: propertyhdl.cxx:63
virtual ULONG STDMETHODCALLTYPE AddRef() override
virtual HRESULT STDMETHODCALLTYPE GetAt(DWORD iProp, PROPERTYKEY *pkey) override
IPropertyStoreCache * m_pCache
Definition: propertyhdl.hxx:72
virtual ULONG STDMETHODCALLTYPE Release() override
virtual HRESULT STDMETHODCALLTYPE Initialize(IStream *pStream, DWORD grfMode) override
#define META_INFO_AUTHOR
Definition: config.hxx:35
#define META_INFO_DOCUMENT_STATISTIC
Definition: config.hxx:49
#define META_INFO_SUBJECT
Definition: config.hxx:36
#define META_INFO_KEYWORDS
Definition: config.hxx:37
#define META_INFO_TITLE
Definition: config.hxx:34
#define META_INFO_DESCRIPTION
Definition: config.hxx:39
#define META_INFO_PAGES
Definition: config.hxx:41
FilterCache * m_pCache
#define TRUE
#define SAL_N_ELEMENTS(arr)
int i
static HINSTANCE g_hModule
Definition: propertyhdl.cxx:40
STDAPI DllCanUnloadNow()
const PROPERTYKEY g_rgPROPERTIES[]
Definition: propertyhdl.cxx:42
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
BOOL WINAPI DllMain(HINSTANCE hInst, ULONG, LPVOID)
size_t const gPropertyTableSize
Definition: propertyhdl.cxx:51
LONG g_DllRefCnt
Definition: propertyhdl.cxx:39
const CLSID CLSID_PROPERTY_HANDLER
Definition: propertyhdl.hxx:26
#define VT_BSTR
const wchar_t *typedef BOOL
LONG
return hr
void OutputDebugStringFormatW(LPCWSTR pFormat,...)
Definition: utilities.hxx:78