1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
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/config.hxx"
31 #include "internal/global.hxx"
32 
33 #ifndef PROPSEETS_HXX_INCLUDED
34 #include "internal/propsheets.hxx"
35 #endif
36 #include "internal/utilities.hxx"
37 #include "internal/resource.h"
38 #include "listviewbuilder.hxx"
39 
40 #if defined _MSC_VER
41 #pragma warning(push, 1)
42 #endif
43 #include <shellapi.h>
44 #if defined _MSC_VER
45 #pragma warning(pop)
46 #endif
47 
48 #include <string>
49 #include <vector>
50 #include <utility>
51 #include <strsafe.h>
52 
53 
54 /*---------------------------------------------
55 	INFO - INFO - INFO - INFO - INFO - INFO
56 
57 	See MSDN "Using Windows XP Visual Styles"
58 	for hints how to enable the new common
59 	control library for our property sheet.
60 
61 	INFO - INFO - INFO - INFO - INFO - INFO
62 ----------------------------------------------*/
63 
64 //-----------------------------
65 //
66 //-----------------------------
67 
68 CPropertySheet::CPropertySheet(long RefCnt) :
69 	m_RefCnt(RefCnt)
70 {
71     OutputDebugStringFormat("CPropertySheet::CTor [%d], [%d]", m_RefCnt, g_DllRefCnt );
72 	InterlockedIncrement(&g_DllRefCnt);
73 }
74 
75 //-----------------------------
76 //
77 //-----------------------------
78 
79 CPropertySheet::~CPropertySheet()
80 {
81     OutputDebugStringFormat("CPropertySheet::DTor [%d], [%d]", m_RefCnt, g_DllRefCnt );
82 	InterlockedDecrement(&g_DllRefCnt);
83 }
84 
85 //-----------------------------
86 // IUnknown methods
87 //-----------------------------
88 
89 HRESULT STDMETHODCALLTYPE CPropertySheet::QueryInterface(
90 	REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
91 {
92 	*ppvObject = 0;
93 
94 	IUnknown* pUnk = 0;
95 	if (IID_IUnknown == riid || IID_IShellExtInit == riid)
96 	{
97 		pUnk = static_cast<IShellExtInit*>(this);
98 		pUnk->AddRef();
99 		*ppvObject = pUnk;
100 		return S_OK;
101 	}
102 	else if (IID_IShellPropSheetExt == riid)
103 	{
104 		pUnk = static_cast<IShellPropSheetExt*>(this);
105 		pUnk->AddRef();
106 		*ppvObject = pUnk;
107 		return S_OK;
108 	}
109 
110 	return E_NOINTERFACE;
111 }
112 
113 //-----------------------------
114 //
115 //-----------------------------
116 
117 ULONG STDMETHODCALLTYPE CPropertySheet::AddRef(void)
118 {
119     OutputDebugStringFormat("CPropertySheet::AddRef [%d]", m_RefCnt );
120 	return InterlockedIncrement(&m_RefCnt);
121 }
122 
123 //-----------------------------
124 //
125 //-----------------------------
126 
127 ULONG STDMETHODCALLTYPE CPropertySheet::Release(void)
128 {
129     OutputDebugStringFormat("CPropertySheet::Release [%d]", m_RefCnt );
130 	long refcnt = InterlockedDecrement(&m_RefCnt);
131 
132 	if (0 == refcnt)
133 		delete this;
134 
135 	return refcnt;
136 }
137 
138 //-----------------------------
139 // IShellExtInit
140 //-----------------------------
141 
142 HRESULT STDMETHODCALLTYPE CPropertySheet::Initialize(
143 	LPCITEMIDLIST /*pidlFolder*/, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/)
144 {
145 	InitCommonControls();
146 
147 	STGMEDIUM medium;
148 	FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
149 
150 	HRESULT hr = lpdobj->GetData(&fe, &medium);
151 
152 	// save the file name
153     if (SUCCEEDED(hr) &&
154 		(1 == DragQueryFileA(
155 			reinterpret_cast<HDROP>(medium.hGlobal),
156 			0xFFFFFFFF,
157 			NULL,
158 			0)))
159 	{
160 	    UINT size = DragQueryFile( reinterpret_cast<HDROP>(medium.hGlobal), 0, 0, 0 );
161 	    if ( size != 0 )
162 	    {
163 	        TCHAR * buffer = new TCHAR[ size + 1 ];
164 	        UINT result_size = DragQueryFile( reinterpret_cast<HDROP>(medium.hGlobal),
165 	                                          0, buffer, size + 1 );
166 	        if ( result_size != 0 )
167 	        {
168 	            std::wstring fname = getShortPathName( buffer );
169 	            std::string fnameA = WStringToString( fname );
170 	            ZeroMemory( m_szFileName, sizeof( m_szFileName ) );
171 	            strncpy( m_szFileName, fnameA.c_str(), ( sizeof( m_szFileName ) - 1 ) );
172 	            hr = S_OK;
173 	        }
174 	        else
175 	            hr = E_INVALIDARG;
176             delete [] buffer;
177 	    }
178 	    else
179 	        hr = E_INVALIDARG;
180     }
181     else
182         hr = E_INVALIDARG;
183 
184 	ReleaseStgMedium(&medium);
185 
186     return hr;
187 }
188 
189 //-----------------------------
190 // IShellPropSheetExt
191 //-----------------------------
192 
193 HRESULT STDMETHODCALLTYPE CPropertySheet::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
194 {
195     // Get OS version (we don't need the summary page on Windows Vista or later)
196     OSVERSIONINFO sInfoOS;
197 
198     ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) );
199     sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
200     GetVersionEx( &sInfoOS );
201     bool bIsVistaOrLater = (sInfoOS.dwMajorVersion >= 6);
202 
203 	std::wstring proppage_header;
204 
205 	PROPSHEETPAGE psp;
206 	ZeroMemory(&psp, sizeof(PROPSHEETPAGEA));
207 
208 	// add the summary property page
209     psp.dwSize      = sizeof(PROPSHEETPAGE);
210     psp.dwFlags     = PSP_DEFAULT | PSP_USETITLE | PSP_USECALLBACK;
211     psp.hInstance   = GetModuleHandle(MODULE_NAME);
212     psp.lParam      = reinterpret_cast<LPARAM>(this);
213 	psp.pfnCallback = reinterpret_cast<LPFNPSPCALLBACK>(CPropertySheet::PropPageSummaryCallback);
214 
215     HPROPSHEETPAGE hPage = NULL;
216 
217 	if ( !bIsVistaOrLater )
218 	{
219 	    proppage_header = GetResString(IDS_PROPPAGE_SUMMARY_TITLE);
220 
221         psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_SUMMARY);
222         psp.pszTitle    = proppage_header.c_str();
223         psp.pfnDlgProc  = reinterpret_cast<DLGPROC>(CPropertySheet::PropPageSummaryProc);
224 
225         hPage = CreatePropertySheetPage(&psp);
226 
227         // keep this instance alive, will be released when the
228         // the page is about to be destroyed in the callback function
229 
230         if (hPage)
231         {
232             if (lpfnAddPage(hPage, lParam))
233                 AddRef();
234             else
235                 DestroyPropertySheetPage(hPage);
236         }
237 	}
238 
239 	// add the statistics property page
240 	proppage_header = GetResString(IDS_PROPPAGE_STATISTICS_TITLE);
241 
242     psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_STATISTICS);
243     psp.pszTitle    = proppage_header.c_str();
244     psp.pfnDlgProc  = reinterpret_cast<DLGPROC>(CPropertySheet::PropPageStatisticsProc);
245 
246     hPage = CreatePropertySheetPage(&psp);
247 
248     if (hPage)
249 	{
250 		if (lpfnAddPage(hPage, lParam))
251 			AddRef();
252 		else
253 			DestroyPropertySheetPage(hPage);
254 	}
255 
256 	// always return success else
257 	// no property sheet will be
258 	// displayed at all
259 	return NOERROR;
260 }
261 
262 //-----------------------------
263 //
264 //-----------------------------
265 
266 HRESULT STDMETHODCALLTYPE CPropertySheet::ReplacePage(
267 	UINT /*uPageID*/, LPFNADDPROPSHEETPAGE /*lpfnReplaceWith*/, LPARAM /*lParam*/)
268 {
269 	return E_NOTIMPL;
270 }
271 
272 //-----------------------------
273 //
274 //-----------------------------
275 
276 UINT CALLBACK CPropertySheet::PropPageSummaryCallback(
277 	HWND /*hwnd*/, UINT uMsg, LPPROPSHEETPAGE ppsp)
278 {
279 	CPropertySheet* pImpl =
280 		reinterpret_cast<CPropertySheet*>(ppsp->lParam);
281 
282 	// release this instance, acquired
283 	// in the AddPages method
284 	if (PSPCB_RELEASE == uMsg)
285 	{
286 		pImpl->Release();
287 	}
288 
289 	return TRUE;
290 }
291 
292 
293 //-----------------------------
294 //
295 //-----------------------------
296 
297 BOOL CALLBACK CPropertySheet::PropPageSummaryProc(HWND hwnd, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
298 {
299 	switch (uiMsg)
300 	{
301 	case WM_INITDIALOG:
302 		{
303 			LPPROPSHEETPAGE psp = reinterpret_cast<LPPROPSHEETPAGE>(lParam);
304 			CPropertySheet* pImpl = reinterpret_cast<CPropertySheet*>(psp->lParam);
305 			pImpl->InitPropPageSummary(hwnd, psp);
306 			return TRUE;
307 		}
308 	}
309 
310 	return FALSE;
311 }
312 
313 //-----------------------------
314 //
315 //-----------------------------
316 
317 BOOL CALLBACK CPropertySheet::PropPageStatisticsProc(HWND hwnd, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
318 {
319 	switch (uiMsg)
320 	{
321 	case WM_INITDIALOG:
322 		{
323 			LPPROPSHEETPAGE psp = reinterpret_cast<LPPROPSHEETPAGE>(lParam);
324 			CPropertySheet* pImpl = reinterpret_cast<CPropertySheet*>(psp->lParam);
325 			pImpl->InitPropPageStatistics(hwnd, psp);
326 			return TRUE;
327 		}
328 	}
329 
330 	return FALSE;
331 }
332 
333 //##################################
334 void CPropertySheet::InitPropPageSummary(HWND hwnd, LPPROPSHEETPAGE /*lppsp*/)
335 {
336     try
337     {
338         CMetaInfoReader metaInfo(m_szFileName);
339 
340         SetWindowText(GetDlgItem(hwnd,IDC_TITLE),    metaInfo.getTagData( META_INFO_TITLE ).c_str() );
341         SetWindowText(GetDlgItem(hwnd,IDC_AUTHOR),   metaInfo.getTagData( META_INFO_AUTHOR ).c_str() );
342         SetWindowText(GetDlgItem(hwnd,IDC_SUBJECT),  metaInfo.getTagData( META_INFO_SUBJECT ).c_str() );
343         SetWindowText(GetDlgItem(hwnd,IDC_KEYWORDS), metaInfo.getTagData( META_INFO_KEYWORDS ).c_str() );
344 
345         // comments read from meta.xml use "\n" for return, but this will not displayable in Edit control, add
346         // "\r" before "\n" to form "\r\n" in order to display return in Edit control.
347         std::wstring tempStr = metaInfo.getTagData( META_INFO_DESCRIPTION ).c_str();
348         std::wstring::size_type itor = tempStr.find ( L"\n" , 0 );
349         while (itor != std::wstring::npos)
350         {
351             tempStr.insert(itor, L"\r");
352             itor = tempStr.find(L"\n", itor + 2);
353         }
354         SetWindowText(GetDlgItem(hwnd,IDC_COMMENTS), tempStr.c_str());
355     }
356     catch (const std::exception&)
357     {
358     }
359 }
360 
361 //---------------------------------
362 /**
363 */
364 void CPropertySheet::InitPropPageStatistics(HWND hwnd, LPPROPSHEETPAGE /*lppsp*/)
365 {
366     try
367     {
368         CMetaInfoReader metaInfo(m_szFileName);
369 
370         document_statistic_reader_ptr doc_stat_reader = create_document_statistic_reader(m_szFileName, &metaInfo);
371 
372         statistic_group_list_t sgl;
373         doc_stat_reader->read(&sgl);
374 
375         list_view_builder_ptr lv_builder = create_list_view_builder(
376             GetDlgItem(hwnd, IDC_STATISTICSLIST),
377             GetResString(IDS_PROPERTY),
378             GetResString(IDS_PROPERTY_VALUE));
379 
380         lv_builder->build(sgl);
381     }
382     catch (const std::exception&)
383     {
384     }
385 }
386