Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
6.8 KiB

  1. #include "priv.h"
  2. #include "infotip.h"
  3. #include "resource.h"
  4. #include <mluisupp.h>
  5. HRESULT ReadProp(IPropertyStorage *ppropstg, PROPID propid, PROPVARIANT *ppropvar)
  6. {
  7. PROPSPEC prspec = { PRSPEC_PROPID, propid };
  8. return ppropstg->ReadMultiple(1, &prspec, ppropvar);
  9. }
  10. STDAPI GetStringProp(IPropertyStorage *ppropstg, PROPID propid, LPTSTR pszBuf, DWORD cchBuf)
  11. {
  12. PROPVARIANT propvar;
  13. *pszBuf = 0;
  14. if (S_OK == ReadProp(ppropstg, propid, &propvar))
  15. {
  16. if (VT_LPWSTR == propvar.vt)
  17. {
  18. SHUnicodeToTChar(propvar.pwszVal, pszBuf, cchBuf);
  19. }
  20. else if (VT_LPSTR == propvar.vt)
  21. {
  22. SHAnsiToTChar(propvar.pszVal, pszBuf, cchBuf);
  23. }
  24. PropVariantClear(&propvar);
  25. }
  26. return *pszBuf ? S_OK : S_FALSE;
  27. }
  28. STDAPI GetFileTimeProp(IPropertyStorage *ppropstg, PROPID propid, LPTSTR pszBuf, DWORD cchBuf)
  29. {
  30. PROPVARIANT propvar;
  31. *pszBuf = 0;
  32. if (S_OK == ReadProp(ppropstg, propid, &propvar))
  33. {
  34. if (VT_FILETIME == propvar.vt)
  35. {
  36. SHFormatDateTime(&propvar.filetime, NULL, pszBuf, cchBuf);
  37. }
  38. PropVariantClear(&propvar);
  39. }
  40. return *pszBuf ? S_OK : S_FALSE;
  41. }
  42. DWORD AppendTipText(LPTSTR pszBuf, int cchBuf, UINT ids, ...)
  43. {
  44. DWORD dwRet;
  45. TCHAR szFmt[64];
  46. va_list ArgList;
  47. if (ids == 0 || 0 == MLLoadString(ids, szFmt, SIZECHARS(szFmt)))
  48. StrCpyN(szFmt, TEXT("%s%s"), ARRAYSIZE(szFmt));
  49. va_start(ArgList, ids);
  50. dwRet = wvnsprintf(pszBuf, cchBuf, szFmt, ArgList);
  51. va_end(ArgList);
  52. return dwRet;
  53. }
  54. STDAPI GetInfoTipFromStorage(IPropertySetStorage *ppropsetstg, const ITEM_PROP *pip, WCHAR **ppszTip)
  55. {
  56. TCHAR szTip[2048];
  57. LPTSTR psz = szTip;
  58. LPCTSTR pszCRLF = TEXT("");
  59. UINT cch, cchMac = SIZECHARS(szTip);
  60. const GUID *pfmtIdLast = NULL;
  61. IPropertyStorage *ppropstg = NULL;
  62. HRESULT hres = E_FAIL;
  63. *ppszTip = NULL;
  64. for (; pip->pfmtid; pip++)
  65. {
  66. // cache the last FMTID and reuse it if the next FMTID is the same
  67. if (!ppropstg || !IsEqualGUID(*pfmtIdLast, *pip->pfmtid))
  68. {
  69. if (ppropstg)
  70. {
  71. ppropstg->Release();
  72. ppropstg = NULL;
  73. }
  74. pfmtIdLast = pip->pfmtid;
  75. ppropsetstg->Open(*pip->pfmtid, STGM_READ | STGM_SHARE_EXCLUSIVE, &ppropstg);
  76. }
  77. if (ppropstg)
  78. {
  79. TCHAR szT[256];
  80. hres = pip->pfnRead(ppropstg, pip->idProp, szT, SIZECHARS(szT));
  81. if (S_OK == hres)
  82. {
  83. cch = AppendTipText(psz, cchMac, pip->idFmtString, pszCRLF, szT);
  84. psz += cch;
  85. cchMac -= cch;
  86. pszCRLF = TEXT("\r\n");
  87. }
  88. else if (hres != S_FALSE)
  89. {
  90. break; // error, exit for loop
  91. }
  92. }
  93. }
  94. if (ppropstg)
  95. ppropstg->Release();
  96. hres = S_FALSE; // assume no tooltip
  97. if (psz != szTip)
  98. {
  99. hres = SHStrDup(szTip, ppszTip);
  100. }
  101. return hres;
  102. }
  103. class CDocFileInfoTip : public IPersistFile, public IQueryInfo
  104. {
  105. public:
  106. CDocFileInfoTip(void);
  107. // IUnknown methods
  108. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  109. STDMETHODIMP_(ULONG) AddRef(void);
  110. STDMETHODIMP_(ULONG) Release(void);
  111. // IPersist methods
  112. STDMETHODIMP GetClassID(CLSID *pclsid);
  113. // IPersistFile methods
  114. STDMETHODIMP IsDirty(void);
  115. STDMETHODIMP Save(LPCOLESTR pcwszFileName, BOOL bRemember);
  116. STDMETHODIMP SaveCompleted(LPCOLESTR pcwszFileName);
  117. STDMETHODIMP Load(LPCOLESTR pcwszFileName, DWORD dwMode);
  118. STDMETHODIMP GetCurFile(LPOLESTR *ppwszFileName);
  119. // IQueryInfo methods
  120. STDMETHODIMP GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip);
  121. STDMETHODIMP GetInfoFlags(DWORD *pdwFlags);
  122. private:
  123. LONG m_cRef;
  124. WCHAR m_szFile[MAX_PATH]; // Name of file we are working on
  125. ~CDocFileInfoTip(void); // Prevent this class from being allocated on the stack or it will fault.
  126. };
  127. CDocFileInfoTip::CDocFileInfoTip(void) : m_cRef(1)
  128. {
  129. DllAddRef();
  130. }
  131. CDocFileInfoTip::~CDocFileInfoTip(void)
  132. {
  133. DllRelease();
  134. }
  135. STDMETHODIMP CDocFileInfoTip::QueryInterface(REFIID riid, void **ppv)
  136. {
  137. static const QITAB qit[] = {
  138. QITABENT(CDocFileInfoTip, IQueryInfo), // IID_IQueryInfo
  139. QITABENT(CDocFileInfoTip, IPersistFile), // IID_IPersistFile
  140. QITABENTMULTI(CDocFileInfoTip, IPersist, IPersistFile), // IID_IPersist
  141. { 0 },
  142. };
  143. return QISearch(this, qit, riid, ppv);
  144. }
  145. STDMETHODIMP_(ULONG) CDocFileInfoTip::AddRef()
  146. {
  147. InterlockedIncrement(&m_cRef);
  148. return m_cRef;
  149. }
  150. STDMETHODIMP_(ULONG) CDocFileInfoTip::Release()
  151. {
  152. if (InterlockedDecrement(&m_cRef))
  153. return m_cRef;
  154. delete this;
  155. return 0;
  156. }
  157. // IPersist methods
  158. STDMETHODIMP CDocFileInfoTip::GetClassID(CLSID *pclsid)
  159. {
  160. *pclsid = CLSID_DocFileInfoTip;
  161. return S_OK;
  162. }
  163. // IPersistFile methods
  164. STDMETHODIMP CDocFileInfoTip::IsDirty(void)
  165. {
  166. return S_FALSE;
  167. }
  168. STDMETHODIMP CDocFileInfoTip::Save(LPCOLESTR pwszFile, BOOL bRemember)
  169. {
  170. return E_NOTIMPL;
  171. }
  172. STDMETHODIMP CDocFileInfoTip::SaveCompleted(LPCOLESTR pwszFile)
  173. {
  174. return S_OK;
  175. }
  176. STDMETHODIMP CDocFileInfoTip::Load(const WCHAR *pwszFile, DWORD dwMode)
  177. {
  178. StrCpyNW(m_szFile, pwszFile, ARRAYSIZE(m_szFile));
  179. return S_OK;
  180. }
  181. STDMETHODIMP CDocFileInfoTip::GetCurFile(WCHAR **ppwszFile)
  182. {
  183. return E_NOTIMPL;
  184. }
  185. // IQueryInfo methods
  186. const ITEM_PROP c_rgDocProps[] = {
  187. { &FMTID_SummaryInformation, PIDSI_AUTHOR, GetStringProp, IDS_AUTHOR },
  188. { &FMTID_SummaryInformation, PIDSI_TITLE, GetStringProp, IDS_DOCTITLE },
  189. { &FMTID_SummaryInformation, PIDSI_SUBJECT, GetStringProp, IDS_SUBJECT },
  190. { &FMTID_SummaryInformation, PIDSI_COMMENTS, GetStringProp, IDS_COMMENTS },
  191. { NULL, 0, 0, 0 },
  192. };
  193. STDMETHODIMP CDocFileInfoTip::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
  194. {
  195. *ppwszTip = NULL;
  196. IStorage *pstg;
  197. HRESULT hres = StgOpenStorage(m_szFile, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstg);
  198. if (SUCCEEDED(hres))
  199. {
  200. IPropertySetStorage *pprop;
  201. hres = pstg->QueryInterface(IID_IPropertySetStorage, (void **)&pprop);
  202. if (SUCCEEDED(hres))
  203. {
  204. hres = GetInfoTipFromStorage(pprop, c_rgDocProps, ppwszTip);
  205. pprop->Release();
  206. }
  207. pstg->Release();
  208. }
  209. return hres;
  210. }
  211. STDMETHODIMP CDocFileInfoTip::GetInfoFlags(DWORD *pdwFlags)
  212. {
  213. *pdwFlags = 0;
  214. return S_OK;
  215. }
  216. STDAPI CDocFileInfoTip_CreateInstance(IUnknown * punkOuter, IUnknown ** ppunk, LPCOBJECTINFO poi)
  217. {
  218. HRESULT hres = E_OUTOFMEMORY;
  219. CDocFileInfoTip *pis = new CDocFileInfoTip();
  220. if (pis)
  221. {
  222. *ppunk = SAFECAST(pis, IQueryInfo *);
  223. hres = S_OK;
  224. }
  225. return hres;
  226. }