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.

427 lines
13 KiB

  1. //==========================================================================================
  2. // HISTDATA helper (should be a static member)
  3. //==========================================================================================
  4. #define CUrlHistoryProp IntsiteProp
  5. //==========================================================================================
  6. // IntsiteProp class implementation
  7. //==========================================================================================
  8. #ifdef DEBUG
  9. /*----------------------------------------------------------
  10. Purpose: Dump the properties in this object
  11. */
  12. STDMETHODIMP_(void)
  13. CUrlHistoryProp::Dump(void)
  14. {
  15. if (IsFlagSet(g_dwDumpFlags, DF_URLPROP))
  16. {
  17. TraceMsg(TF_ALWAYS, " Intsite Property obj: %s", m_szURL);
  18. URLProp::Dump();
  19. }
  20. }
  21. #endif
  22. /*----------------------------------------------------------
  23. Purpose: Constructor for URLProp
  24. */
  25. CUrlHistoryProp::CUrlHistoryProp(void)
  26. {
  27. // Don't validate this until after construction.
  28. // This object should only be allocated, not used on the stack,
  29. // because we don't zero-initialize the member variables.
  30. // Here's a sanity assertion.
  31. ASSERT(NULL == m_pintshcut);
  32. ASSERT(IS_VALID_STRUCT_PTR(this, CIntsiteProp));
  33. return;
  34. }
  35. /*----------------------------------------------------------
  36. Purpose: Destructor for CUrlHistoryProp
  37. */
  38. CUrlHistoryProp::~CUrlHistoryProp(void)
  39. {
  40. if (m_pintshcut)
  41. {
  42. if (!m_fPrivate)
  43. m_pintshcut->Release();
  44. m_pintshcut = NULL;
  45. }
  46. return;
  47. }
  48. STDAPI CIntsiteProp_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut)
  49. {
  50. HRESULT hres;
  51. *ppvOut = NULL;
  52. ASSERT(punkOuter==NULL)
  53. IUnknown * piunk = (IUnknown *)new IntsiteProp;
  54. if ( !piunk )
  55. {
  56. hres = E_OUTOFMEMORY;
  57. }
  58. else
  59. {
  60. hres = piunk->QueryInterface(riid, ppvOut);
  61. piunk->Release();
  62. }
  63. return hres; // S_OK or E_NOINTERFACE
  64. }
  65. HRESULT CUrlHistoryProp::Init(void)
  66. {
  67. return URLProp::Init();
  68. }
  69. STDMETHODIMP CUrlHistoryProp::InitFromDB(LPCTSTR pszURL, Intshcut *pintshcut, BOOL fPrivObj)
  70. {
  71. // TraceMsg(DM_HISTPROP, "CUHP::InitFromDB called for %s", pszURL);
  72. // Initialize the in-memory property storage from the file
  73. // and database
  74. HRESULT hres = Init();
  75. if (SUCCEEDED(hres))
  76. {
  77. if (NULL == m_pintshcut)
  78. {
  79. m_fPrivate = fPrivObj;
  80. if (!m_fPrivate)
  81. pintshcut->AddRef();
  82. m_pintshcut = pintshcut;
  83. }
  84. else
  85. {
  86. // We can't switch from Private->Public or visaversa.
  87. ASSERT(fPrivObj == m_fPrivate);
  88. }
  89. if (pszURL)
  90. {
  91. // Is this really a URL??
  92. PARSEDURL pu;
  93. pu.cbSize = SIZEOF(pu);
  94. hres = ParseURL(pszURL, &pu);
  95. if (S_OK == hres)
  96. {
  97. // Yes; go ahead and initialize
  98. StrCpyN(m_szURL, pszURL, SIZECHARS(m_szURL));
  99. hres = LoadFromDB(pszURL);
  100. }
  101. }
  102. }
  103. return hres;
  104. }
  105. HRESULT CUrlHistoryProp::LoadFromDB(
  106. IN LPCTSTR pszURL)
  107. {
  108. TraceMsg(DM_HISTPROP, "CUHP::LoadFromDB called for %s", pszURL);
  109. CEI_PREALLOC buf;
  110. CUrlHistory::s_ConvertToPrefixedUrlW(pszURL, buf.szPrefixedUrl, ARRAYSIZE(buf.szPrefixedUrl), &buf.pszFragment);
  111. CUrlHistory::s_RetrievePrefixedUrlInfo(buf.szPrefixedUrl, &buf);
  112. //
  113. // if there is already an entry for this Url, then we will reuse some of the
  114. // settings. retrieve the relevant info if possible.
  115. //
  116. if (buf.pcei) {
  117. CHistoryData* phdPrev = CHistoryData::s_GetHistoryData(buf.pcei);
  118. if (phdPrev) {
  119. //
  120. // Initialize non-string properties first
  121. //
  122. const static PROPSPEC c_aprspec[] = {
  123. { PRSPEC_PROPID, PID_INTSITE_FLAGS },
  124. { PRSPEC_PROPID, PID_INTSITE_LASTVISIT },
  125. { PRSPEC_PROPID, PID_INTSITE_LASTMOD },
  126. { PRSPEC_PROPID, PID_INTSITE_WATCH },
  127. };
  128. PROPVARIANT apropvar[ARRAYSIZE(c_aprspec)] = { 0 };
  129. apropvar[0].vt = VT_UI4;
  130. apropvar[0].lVal = phdPrev->dwFlags;
  131. apropvar[1].vt = VT_FILETIME;
  132. apropvar[1].filetime = buf.pcei->LastAccessTime;
  133. apropvar[2].vt = VT_FILETIME;
  134. apropvar[2].filetime = buf.pcei->LastModifiedTime;
  135. apropvar[3].vt = VT_UI4;
  136. apropvar[3].lVal = phdPrev->dwWatch;
  137. TraceMsg(DM_HISTPROP, "CUHP::InitFromDB calling WriteMultiple (wFlags=%x)", phdPrev->dwFlags);
  138. WriteMultiple(ARRAYSIZE(c_aprspec), c_aprspec, apropvar, 0);
  139. PropStg_DirtyMultiple(m_hstg, ARRAYSIZE(c_aprspec), c_aprspec, FALSE);
  140. //
  141. // Then, initialize others
  142. //
  143. PROPSPEC prspec;
  144. prspec.ulKind = PRSPEC_PROPID;
  145. for (const HISTEXTRA* phextPrev = phdPrev->_GetExtra();
  146. phextPrev && !phextPrev->IsTerminator();
  147. phextPrev = phextPrev->GetNextFast())
  148. {
  149. TraceMsg(DM_HISTPROP, "CUHP::InitFromDB found HISTEXTRA (id=%d, vt=%d)",
  150. phextPrev->idExtra, phextPrev->cbExtra);
  151. WCHAR wszBuf[MAX_URL_STRING]; // NOTES: scope must be right
  152. apropvar[0].vt = phextPrev->vtExtra;
  153. switch(phextPrev->vtExtra) {
  154. case VT_LPWSTR:
  155. apropvar[0].pwszVal = (LPWSTR)phextPrev->abExtra;
  156. break;
  157. case VT_LPSTR:
  158. //
  159. // Notice that we always convert it to LPWSTR
  160. //
  161. {
  162. apropvar[0].pwszVal = wszBuf;
  163. LPCSTR pszExtra = (LPCSTR)phextPrev->abExtra;
  164. AnsiToUnicode(pszExtra, wszBuf, ARRAYSIZE(wszBuf));
  165. apropvar[0].vt = VT_LPWSTR;
  166. }
  167. break;
  168. case VT_UI4:
  169. case VT_I4:
  170. apropvar[0].lVal = *(DWORD*)phextPrev->abExtra;
  171. break;
  172. case VT_NULL:
  173. ASSERT(phextPrev->idExtra == PID_INTSITE_FRAGMENT);
  174. continue;
  175. default:
  176. ASSERT(0);
  177. continue;
  178. }
  179. prspec.propid = phextPrev->idExtra;
  180. WriteMultiple(1, &prspec, apropvar, 0);
  181. PropStg_DirtyMultiple(m_hstg, 1, &prspec, FALSE);
  182. }
  183. } else {
  184. TraceMsg(DM_HISTPROP, "CUHP::LoadFromDB can't get phdPrev");
  185. }
  186. } else {
  187. TraceMsg(DM_HISTPROP, "CUHP::LoadFromDB can't get pcei");
  188. }
  189. return S_OK;
  190. }
  191. struct URLHIST_ENUMPARAM {
  192. CUrlHistoryProp* that;
  193. INTERNET_CACHE_ENTRY_INFO cei;
  194. LPINTERNET_CACHE_ENTRY_INFO pceiPrev;
  195. CHistoryData* phdPrev;
  196. LPHISTEXTRA phextCur;
  197. UINT cbHistExtra;
  198. BOOL fDirty;
  199. };
  200. STDAPI s_CommitHistItem(
  201. IN PROPID propid,
  202. IN PROPVARIANT * ppropvar,
  203. IN LPARAM lParam)
  204. {
  205. URLHIST_ENUMPARAM* peparam = (URLHIST_ENUMPARAM*)lParam;
  206. CHistoryData* phdNew = (CHistoryData*)peparam->cei.lpHeaderInfo;
  207. TraceMsg(DM_HISTEXTRA, "CUHP::s_CommitHistItem called for id=%d vt=%d (phextCur=%x)",
  208. propid, ppropvar->vt, peparam->phextCur);
  209. UINT cbExtra = 0;
  210. UINT cbRequired;
  211. switch(propid) {
  212. case PID_INTSITE_FLAGS:
  213. if (ppropvar->vt == VT_UI4 && phdNew) {
  214. TraceMsg(DM_HISTPROP, "CUHP::s_CommitHistItem updating PID_INSITE_FLAGS (%x to %x)",
  215. phdNew->dwFlags, ppropvar->lVal);
  216. phdNew->dwFlags = ppropvar->lVal;
  217. peparam->fDirty = TRUE;
  218. }
  219. break;
  220. case PID_INTSITE_WATCH:
  221. if (ppropvar->vt == VT_UI4 && phdNew) {
  222. TraceMsg(DM_HISTPROP, "CUHP::s_CommitHistItem updating PID_INSITE_WATCH (%x to %x)",
  223. phdNew->dwFlags, ppropvar->lVal);
  224. phdNew->dwWatch = ppropvar->lVal;
  225. peparam->fDirty = TRUE;
  226. }
  227. break;
  228. case PID_INTSITE_LASTVISIT:
  229. case PID_INTSITE_LASTMOD:
  230. // They are read-only. We can change it if we want.
  231. ASSERT(0);
  232. break;
  233. default:
  234. switch(ppropvar->vt) {
  235. case VT_UI4:
  236. case VT_I4:
  237. cbExtra = DW_ALIGNED(SIZEOF(HISTEXTRA)-SIZEOF(peparam->phextCur->abExtra)+SIZEOF(UINT));
  238. if (peparam->phextCur) {
  239. peparam->phextCur->cbExtra = cbExtra;
  240. peparam->phextCur->idExtra = propid;
  241. peparam->phextCur->vtExtra = ppropvar->vt;
  242. *(DWORD*)peparam->phextCur->abExtra = ppropvar->lVal;
  243. peparam->fDirty = TRUE;
  244. }
  245. break;
  246. case VT_LPWSTR:
  247. cbRequired = WideCharToMultiByte(CP_ACP, 0, ppropvar->pwszVal, -1,
  248. NULL, 0, NULL, NULL);
  249. cbExtra = DW_ALIGNED(SIZEOF(HISTEXTRA) + cbRequired);
  250. if (peparam->phextCur)
  251. {
  252. peparam->phextCur->cbExtra = cbExtra;
  253. peparam->phextCur->idExtra = propid;
  254. peparam->phextCur->vtExtra = VT_LPSTR;
  255. WideCharToMultiByte(CP_ACP, 0, ppropvar->pwszVal, -1,
  256. (LPSTR)peparam->phextCur->abExtra, cbRequired, NULL, NULL);
  257. peparam->fDirty = TRUE;
  258. }
  259. break;
  260. case VT_EMPTY:
  261. if (peparam->phextCur) {
  262. peparam->fDirty = TRUE;
  263. }
  264. break;
  265. default:
  266. ASSERT(0);
  267. break;
  268. }
  269. if (peparam->phextCur) {
  270. // We are saving the data, move the write pointer.
  271. TraceMsg(DM_HISTEXTRA, "s_CommitHistItem moving phextCur forward %d bytes",
  272. peparam->phextCur->cbExtra);
  273. peparam->phextCur = peparam->phextCur->GetNextFastForSave();
  274. ASSERT(peparam->phextCur->cbExtra == 0);
  275. } else {
  276. // We are calcurating the required size, just add the size.
  277. TraceMsg(DM_HISTEXTRA, "s_CommitHistItem adding %d", cbExtra);
  278. peparam->cbHistExtra += cbExtra;
  279. // Remove existing one.
  280. if (peparam->phdPrev) {
  281. // FEATURE: Bad const to non-const cast
  282. HISTEXTRA* phextPrev =
  283. (HISTEXTRA*)peparam->phdPrev->_FindExtra(propid);
  284. if (phextPrev) {
  285. TraceMsg(DM_HISTEXTRA, "s_CommitHistItem invalidate an old one id=%d %d bytes",
  286. phextPrev->idExtra, phextPrev->cbExtra);
  287. phextPrev->vtExtra = VT_EMPTY;
  288. }
  289. }
  290. }
  291. }
  292. return S_OK;
  293. };
  294. HRESULT CUrlHistoryProp::Commit(IN DWORD dwFlags)
  295. {
  296. TraceMsg(DM_HISTPROP, "CUHP::Commit called for %s", m_szURL);
  297. CEI_PREALLOC buf;
  298. CUrlHistory::s_ConvertToPrefixedUrlW(m_szURL, buf.szPrefixedUrl, ARRAYSIZE(buf.szPrefixedUrl), &buf.pszFragment);
  299. CUrlHistory::s_RetrievePrefixedUrlInfo(buf.szPrefixedUrl, &buf);
  300. HRESULT hres;
  301. URLHIST_ENUMPARAM eparam = { this };
  302. ASSERT(eparam.fDirty == FALSE);
  303. eparam.pceiPrev = buf.pcei;
  304. if (eparam.pceiPrev) {
  305. eparam.cei = *eparam.pceiPrev;
  306. eparam.phdPrev = CHistoryData::s_GetHistoryData(eparam.pceiPrev);
  307. }
  308. // First, enemerate once to get the size for extra.
  309. eparam.cei.lpHeaderInfo = NULL;
  310. eparam.cbHistExtra = 0;
  311. hres = PropStg_Enum(m_hstg, PSTGEF_DIRTY, s_CommitHistItem, (LPARAM)&eparam);
  312. DWORD dwFlagsPrev = 0;
  313. if (eparam.phdPrev) {
  314. eparam.cbHistExtra += eparam.phdPrev->GetTotalExtraSize();
  315. dwFlagsPrev = eparam.phdPrev->dwFlags;
  316. }
  317. TraceMsg(DM_HISTEXTRA, "CUHP::Commit total size is %d", eparam.cbHistExtra);
  318. CHistoryData* phdNew = CHistoryData::s_AllocateHeaderInfo(
  319. eparam.cbHistExtra, eparam.phdPrev,
  320. &eparam.cei.dwHeaderInfoSize);
  321. if (phdNew) {
  322. eparam.cei.lpHeaderInfo = (LPTSTR)phdNew;
  323. eparam.phextCur = phdNew->_GetExtra();
  324. // Enumerate again to fill the extra data.
  325. hres = PropStg_Enum(m_hstg, PSTGEF_DIRTY, s_CommitHistItem, (LPARAM)&eparam);
  326. if (eparam.fDirty)
  327. {
  328. if (eparam.phdPrev) {
  329. eparam.phdPrev->CopyExtra(eparam.phextCur);
  330. }
  331. TraceMsg(DM_HISTPROP, "CUHP::Commit It's dirty. save it (header = %d bytes)",
  332. eparam.cei.dwHeaderInfoSize);
  333. ASSERT(eparam.cbHistExtra == phdNew->GetTotalExtraSize());
  334. CUrlHistory::s_CommitUrlCacheEntry(buf.szPrefixedUrl, &eparam.cei);
  335. if ((dwFlagsPrev & PIDISF_RECENTLYCHANGED)
  336. != (phdNew->dwFlags & PIDISF_RECENTLYCHANGED))
  337. {
  338. // Yes; update the images
  339. CUrlHistory::s_UpdateIcon(m_pintshcut, dwFlagsPrev);
  340. }
  341. }
  342. LocalFree(phdNew);
  343. phdNew = NULL;
  344. }
  345. return hres;
  346. }