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