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