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/global.hxx" 31 #include "internal/infotips.hxx" 32 #include "internal/shlxthdl.hxx" 33 #include "internal/metainforeader.hxx" 34 #include "internal/contentreader.hxx" 35 #include "internal/utilities.hxx" 36 #include "internal/registry.hxx" 37 #include "internal/fileextensions.hxx" 38 #include "internal/iso8601_converter.hxx" 39 #include "internal/config.hxx" 40 41 #include "internal/resource.h" 42 #include <stdio.h> 43 #include <utility> 44 #include <stdlib.h> 45 46 47 #define MAX_STRING 80 48 #define KB 1024.0 49 const std::wstring WSPACE = std::wstring(SPACE); 50 51 //----------------------------- 52 // 53 //----------------------------- 54 55 CInfoTip::CInfoTip(long RefCnt) : 56 m_RefCnt(RefCnt) 57 { 58 ZeroMemory(m_szFileName, sizeof(m_szFileName)); 59 InterlockedIncrement(&g_DllRefCnt); 60 } 61 62 //----------------------------- 63 // 64 //----------------------------- 65 66 CInfoTip::~CInfoTip() 67 { 68 InterlockedDecrement(&g_DllRefCnt); 69 } 70 71 //----------------------------- 72 // IUnknown methods 73 //----------------------------- 74 75 HRESULT STDMETHODCALLTYPE CInfoTip::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) 76 { 77 *ppvObject = 0; 78 79 IUnknown* pUnk = 0; 80 81 if (IID_IUnknown == riid || IID_IQueryInfo == riid) 82 { 83 pUnk = static_cast<IQueryInfo*>(this); 84 pUnk->AddRef(); 85 *ppvObject = pUnk; 86 return S_OK; 87 } 88 else if (IID_IPersistFile == riid) 89 { 90 pUnk = static_cast<IPersistFile*>(this); 91 pUnk->AddRef(); 92 *ppvObject = pUnk; 93 return S_OK; 94 } 95 96 return E_NOINTERFACE; 97 } 98 99 //---------------------------- 100 // 101 //---------------------------- 102 103 ULONG STDMETHODCALLTYPE CInfoTip::AddRef(void) 104 { 105 return InterlockedIncrement(&m_RefCnt); 106 } 107 108 //---------------------------- 109 // 110 //---------------------------- 111 112 ULONG STDMETHODCALLTYPE CInfoTip::Release( void) 113 { 114 long refcnt = InterlockedDecrement(&m_RefCnt); 115 116 if (0 == m_RefCnt) 117 delete this; 118 119 return refcnt; 120 } 121 122 //********************helper functions for GetInfoTip functions********************** 123 124 /** get file type infomation from registry. 125 */ 126 std::wstring getFileTypeInfo(const std::string& file_extension) 127 { 128 char extKeyValue[MAX_STRING]; 129 char typeKeyValue[MAX_STRING]; 130 ::std::string sDot("."); 131 if (QueryRegistryKey(HKEY_CLASSES_ROOT, (sDot.append(file_extension)).c_str(), "", extKeyValue, MAX_STRING)) 132 if (QueryRegistryKey( HKEY_CLASSES_ROOT, extKeyValue, "",typeKeyValue, MAX_STRING)) 133 return StringToWString(typeKeyValue); 134 135 return EMPTY_STRING; 136 } 137 138 /** get file size. 139 */ 140 DWORD getSizeOfFile( char* FileName ) 141 { 142 HANDLE hFile = CreateFile(StringToWString(FileName).c_str(), // open file 143 GENERIC_READ, // open for reading 144 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, // share for all operations 145 NULL, // no security 146 OPEN_EXISTING, // existing file only 147 FILE_ATTRIBUTE_NORMAL, // normal file 148 NULL); // no attr. template 149 150 if (hFile != INVALID_HANDLE_VALUE) 151 { 152 DWORD dwSize = GetFileSize( HANDLE(hFile), NULL ); 153 CloseHandle( HANDLE(hFile) ); 154 return dwSize; 155 } 156 157 return INVALID_FILE_SIZE; 158 } 159 160 /** format file size in to be more readable. 161 */ 162 std::wstring formatSizeOfFile( DWORD dwSize ) 163 { 164 if ( dwSize < 1000 ) 165 { 166 char buffer[3]; 167 int dFileSize = dwSize; 168 169 _itoa( dFileSize, buffer, 10 ); 170 return StringToWString( buffer ).append(StringToWString("B")); 171 } 172 173 char *buffer=NULL; 174 int decimal, sign; 175 double dFileSize = (double)dwSize/(double)KB; 176 177 buffer = _fcvt( dFileSize, 1, &decimal, &sign ); 178 179 ::std::wstring wsTemp = StringToWString( buffer ); 180 int pos=decimal % 3; 181 ::std::wstring wsBuffer = wsTemp.substr( 0,pos); 182 183 if ( decimal ) 184 for (;decimal - pos > 2;pos += 3) 185 { 186 if (pos) 187 wsBuffer.append(StringToWString(",")); 188 wsBuffer.append( wsTemp.substr( pos, 3) ); 189 } 190 else 191 wsBuffer.append(StringToWString("0")); 192 193 wsBuffer.append(StringToWString(".")); 194 wsBuffer.append(wsTemp.substr( decimal, wsTemp.size()-decimal )); 195 wsBuffer.append(StringToWString("KB")); 196 197 return wsBuffer; 198 } 199 200 201 /** get file size infomation. 202 */ 203 std::wstring getFileSizeInfo(char* FileName) 204 { 205 DWORD dwSize=getSizeOfFile(FileName); 206 if (dwSize != INVALID_FILE_SIZE) 207 return formatSizeOfFile( dwSize ); 208 209 return EMPTY_STRING; 210 } 211 212 //---------------------------- 213 // IQueryInfo methods 214 //---------------------------- 215 216 HRESULT STDMETHODCALLTYPE CInfoTip::GetInfoTip(DWORD /*dwFlags*/, wchar_t** ppwszTip) 217 { 218 std::wstring msg; 219 const std::wstring CONST_SPACE(SPACE); 220 221 //display File Type, no matter other info is loaded successfully or not. 222 std::wstring tmpTypeStr = getFileTypeInfo( get_file_name_extension(m_szFileName) ); 223 if ( tmpTypeStr != EMPTY_STRING ) 224 { 225 msg += GetResString(IDS_TYPE_COLON) + CONST_SPACE; 226 msg += tmpTypeStr; 227 } 228 229 try 230 { 231 CMetaInfoReader meta_info_accessor(m_szFileName); 232 233 //display document title; 234 if ( meta_info_accessor.getTagData( META_INFO_TITLE ).length() > 0) 235 { 236 if ( msg != EMPTY_STRING ) 237 msg += L"\n"; 238 msg += GetResString(IDS_TITLE_COLON) + CONST_SPACE; 239 msg += meta_info_accessor.getTagData( META_INFO_TITLE ); 240 } 241 else 242 { 243 if ( msg != EMPTY_STRING ) 244 msg += L"\n"; 245 msg += GetResString(IDS_TITLE_COLON) + CONST_SPACE; 246 msg += m_FileNameOnly; 247 } 248 249 //display document author; 250 if ( meta_info_accessor.getTagData( META_INFO_AUTHOR ).length() > 0) 251 { 252 if ( msg != EMPTY_STRING ) 253 msg += L"\n"; 254 msg += GetResString( IDS_AUTHOR_COLON ) + CONST_SPACE; 255 msg += meta_info_accessor.getTagData( META_INFO_AUTHOR ); 256 } 257 258 //display document subject; 259 if ( meta_info_accessor.getTagData( META_INFO_SUBJECT ).length() > 0) 260 { 261 if ( msg != EMPTY_STRING ) 262 msg += L"\n"; 263 msg += GetResString(IDS_SUBJECT_COLON) + CONST_SPACE; 264 msg += meta_info_accessor.getTagData( META_INFO_SUBJECT ); 265 } 266 267 //display document description; 268 if ( meta_info_accessor.getTagData( META_INFO_DESCRIPTION ).length() > 0) 269 { 270 if ( msg != EMPTY_STRING ) 271 msg += L"\n"; 272 msg += GetResString( IDS_COMMENTS_COLON ) + CONST_SPACE; 273 msg += meta_info_accessor.getTagData( META_INFO_DESCRIPTION ); 274 } 275 276 //display midified time formated into locale representation. 277 if ( iso8601_date_to_local_date(meta_info_accessor.getTagData(META_INFO_MODIFIED )).length() > 0) 278 { 279 if ( msg != EMPTY_STRING ) 280 msg += L"\n"; 281 msg += GetResString( IDS_MODIFIED_COLON ) + CONST_SPACE; 282 msg += iso8601_date_to_local_date(meta_info_accessor.getTagData(META_INFO_MODIFIED )); 283 } 284 } 285 catch (const std::exception&) 286 { 287 //return E_FAIL; 288 } 289 290 //display file size, no matter other infomation is loaded successfully or not. 291 std::wstring tmpSizeStr = getFileSizeInfo( m_szFileName ); 292 if ( tmpSizeStr != EMPTY_STRING ) 293 { 294 msg += L"\n"; 295 msg += GetResString( IDS_SIZE_COLON ) + CONST_SPACE; 296 msg += tmpSizeStr; 297 } 298 299 300 //finalize and assignthe string. 301 LPMALLOC lpMalloc; 302 HRESULT hr = SHGetMalloc(&lpMalloc); 303 304 if (SUCCEEDED(hr)) 305 { 306 size_t len = sizeof(wchar_t) * msg.length() + sizeof(wchar_t); 307 wchar_t* pMem = reinterpret_cast<wchar_t*>(lpMalloc->Alloc(len)); 308 309 ZeroMemory(pMem, len); 310 311 msg.copy(pMem,msg.length()); 312 313 *ppwszTip = pMem; 314 lpMalloc->Release(); 315 316 return S_OK; 317 } 318 319 return E_FAIL; 320 } 321 322 //---------------------------- 323 // 324 //---------------------------- 325 326 HRESULT STDMETHODCALLTYPE CInfoTip::GetInfoFlags(DWORD * /*pdwFlags*/ ) 327 { 328 return E_NOTIMPL; 329 } 330 331 //---------------------------- 332 // IPersist methods 333 //---------------------------- 334 335 HRESULT STDMETHODCALLTYPE CInfoTip::GetClassID(CLSID* pClassID) 336 { 337 pClassID = const_cast<CLSID*>(&CLSID_INFOTIP_HANDLER); 338 return S_OK; 339 } 340 341 //---------------------------- 342 // IPersistFile methods 343 //---------------------------- 344 345 HRESULT STDMETHODCALLTYPE CInfoTip::Load(LPCOLESTR pszFileName, DWORD /*dwMode*/) 346 { 347 std::wstring fname = pszFileName; 348 349 // there must be a '\' and there must even be an 350 // extension, else we would not have been called 351 std::wstring::iterator begin = fname.begin() + fname.find_last_of(L"\\") + 1; 352 std::wstring::iterator end = fname.end(); 353 354 m_FileNameOnly = std::wstring(begin, end); 355 356 fname = getShortPathName( fname ); 357 358 std::string fnameA = WStringToString(fname); 359 360 // #115531# 361 // ZeroMemory because strncpy doesn't '\0'-terminates the destination 362 // string; reserve the last place in the buffer for the final '\0' 363 // that's why '(sizeof(m_szFileName) - 1)' 364 ZeroMemory(m_szFileName, sizeof(m_szFileName)); 365 strncpy(m_szFileName, fnameA.c_str(), (sizeof(m_szFileName) - 1)); 366 367 return S_OK; 368 } 369 370 //---------------------------- 371 // 372 //---------------------------- 373 374 HRESULT STDMETHODCALLTYPE CInfoTip::IsDirty(void) 375 { 376 return E_NOTIMPL; 377 } 378 379 //---------------------------- 380 // 381 //---------------------------- 382 383 HRESULT STDMETHODCALLTYPE CInfoTip::Save(LPCOLESTR /*pszFileName*/, BOOL /*fRemember*/) 384 { 385 return E_NOTIMPL; 386 } 387 388 //---------------------------- 389 // 390 //---------------------------- 391 392 HRESULT STDMETHODCALLTYPE CInfoTip::SaveCompleted(LPCOLESTR /*pszFileName*/) 393 { 394 return E_NOTIMPL; 395 } 396 397 //---------------------------- 398 // 399 //---------------------------- 400 401 HRESULT STDMETHODCALLTYPE CInfoTip::GetCurFile(LPOLESTR __RPC_FAR * /*ppszFileName*/) 402 { 403 return E_NOTIMPL; 404 } 405