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