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.

287 lines
6.8 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // multi.cpp
  5. //
  6. // Contents:
  7. // Cache node test which creates multiple nodes, then performs
  8. // various data tests on them.
  9. //
  10. // History:
  11. //
  12. // 04-Sep-94 davepl Created
  13. //
  14. //-----------------------------------------------------------------------------
  15. #include "headers.hxx"
  16. #pragma hdrstop
  17. //+----------------------------------------------------------------------------
  18. //
  19. // Member: TestInstance::MultiCache
  20. //
  21. // Synopsis: Caches N unique nodes, where N is large (>100). Saves
  22. // the cache, then reloads it to compare.
  23. //
  24. // Arguments: [dwCount] Number of new nodes to cache
  25. //
  26. // Returns: HRESULT
  27. //
  28. // Notes:
  29. //
  30. // History: 24-Aug-94 Davepl Created
  31. //
  32. //-----------------------------------------------------------------------------
  33. HRESULT TestInstance::MultiCache(DWORD dwCount)
  34. {
  35. HRESULT hr;
  36. DWORD iCFGEN = 0,
  37. iNODES = 0,
  38. iSDATA = 0;
  39. TraceLog Log(NULL, "TestInstance::MultiCache", GS_CACHE, VB_MINIMAL);
  40. Log.OnEntry (" ( %d )\n", dwCount);
  41. Log.OnExit (" ( %X )\n", &hr);
  42. //
  43. // A temporary buffer for creating text clipformat names
  44. //
  45. char szFormatName[ MAX_BUF ];
  46. //
  47. // An array of UINTs to hold our private clipformats, and an
  48. // array of DWORDS to hold the connection IDs
  49. //
  50. CLIPFORMAT *acfArray = (CLIPFORMAT *) malloc(dwCount * sizeof(CLIPFORMAT));
  51. if (NULL == acfArray)
  52. {
  53. return E_OUTOFMEMORY;
  54. }
  55. DWORD *adwConnections = (DWORD *) malloc(dwCount * sizeof(DWORD));
  56. if (NULL == adwConnections)
  57. {
  58. free(acfArray);
  59. return E_OUTOFMEMORY;
  60. }
  61. //
  62. // Generate N private clipformats
  63. //
  64. for (iCFGEN=0; iCFGEN < dwCount; iCFGEN++)
  65. {
  66. sprintf(szFormatName, "LocalFormat%d", iCFGEN);
  67. acfArray[iCFGEN] = (WORD) RegisterClipboardFormat(szFormatName);
  68. if (0 == acfArray[iCFGEN])
  69. {
  70. free(acfArray);
  71. return HRESULT_FROM_WIN32(GetLastError());
  72. }
  73. }
  74. //
  75. // Cache N nodes based on those formats
  76. //
  77. FORMATETC fetc =
  78. {
  79. 0, // Clipformat
  80. NULL, // DVTargetDevice
  81. DVASPECT_CONTENT, // Aspect
  82. -1, // Index
  83. TYMED_HGLOBAL // TYMED
  84. };
  85. STGMEDIUM stgm;
  86. for (iNODES = 0; iNODES < dwCount; iNODES++)
  87. {
  88. fetc.cfFormat = acfArray[iNODES];
  89. hr = m_pOleCache->Cache(&fetc, ADVF_PRIMEFIRST, &adwConnections[iNODES]);
  90. // We are expecting the cache to return CACHE_S_FORMATETC_NOTSUPPORTED
  91. // for this data, since it cannot draw it.
  92. hr = MassageErrorCode(CACHE_S_FORMATETC_NOTSUPPORTED, hr);
  93. if (S_OK != hr)
  94. {
  95. break;
  96. }
  97. }
  98. //
  99. // If all went well adding the nodes, proceed to SetData into
  100. // each of the nodes with some unique data
  101. //
  102. if (S_OK == hr)
  103. {
  104. for (iSDATA = 0; iSDATA < dwCount; iSDATA++)
  105. {
  106. HGLOBAL hTmp = GlobalAlloc(GMEM_MOVEABLE, sizeof(DWORD));
  107. if (NULL == hTmp)
  108. {
  109. break;
  110. }
  111. DWORD * pdw = (DWORD *) GlobalLock(hTmp);
  112. if (NULL == pdw)
  113. {
  114. GlobalFree(hTmp);
  115. break;
  116. }
  117. //
  118. // Set the data in the HGLOBAL equal to the clipformat
  119. // for this node
  120. //
  121. *pdw = iSDATA;
  122. GlobalUnlock(hTmp);
  123. stgm.tymed = TYMED_HGLOBAL;
  124. stgm.hGlobal = hTmp;
  125. fetc.cfFormat = acfArray[iSDATA];
  126. hr = m_pOleCache->SetData(&fetc, &stgm, TRUE /* fRelease */);
  127. if (S_OK != hr)
  128. {
  129. break;
  130. }
  131. }
  132. }
  133. //
  134. // Save the cache and reload it
  135. //
  136. if (S_OK == hr)
  137. {
  138. hr = SaveAndReload();
  139. }
  140. //
  141. // Just to make things interesting, let's DiscardCache before we
  142. // start looking for data. This will force the cache to demand-load
  143. // the data as we ask for it. Since we know the cache is not dirty,
  144. // there's no value (practical or from a test perspective) in asking
  145. // the DiscardCache to save along the way.
  146. //
  147. if (S_OK == hr)
  148. {
  149. hr = m_pOleCache2->DiscardCache(DISCARDCACHE_NOSAVE);
  150. }
  151. if (S_OK == hr)
  152. {
  153. for (iSDATA = 0; iSDATA < dwCount; iSDATA++)
  154. {
  155. //
  156. // For each of the cache nodes we added, try to
  157. // get the data that was saved in the cache under
  158. // that clipformat
  159. //
  160. fetc.cfFormat = acfArray[iSDATA];
  161. hr = m_pDataObject->GetData(&fetc, &stgm);
  162. if (S_OK != hr)
  163. {
  164. ReleaseStgMedium(&stgm);
  165. break;
  166. }
  167. //
  168. // Lock the HGLOBAL and compare what is in the cache
  169. // node to what we expect should be there (the index
  170. // into our clipboard format table
  171. //
  172. DWORD * pdw = (DWORD *) GlobalLock(stgm.hGlobal);
  173. if (NULL == pdw)
  174. {
  175. hr = E_OUTOFMEMORY;
  176. break;
  177. }
  178. if (*pdw != iSDATA)
  179. {
  180. hr = E_FAIL;
  181. GlobalUnlock(stgm.hGlobal);
  182. ReleaseStgMedium(&stgm);
  183. break;
  184. }
  185. GlobalUnlock(stgm.hGlobal);
  186. ReleaseStgMedium(&stgm);
  187. }
  188. }
  189. //
  190. // We want to remove all of the cache nodes we have added.
  191. // Unforunately, there is no easy way to do this; we have to
  192. // enumerate over the cache and toss nodes as we find them, even
  193. // though we _know_ everything about the nodes. Sigh...
  194. //
  195. //
  196. // Get an enumerator on the cache
  197. //
  198. LPENUMSTATDATA pEsd;
  199. if (S_OK == hr)
  200. {
  201. hr = m_pOleCache->EnumCache(&pEsd);
  202. }
  203. //
  204. // Since we've got a large number of cache nodes in the cache,
  205. // now is a perfect time to run the generic enumerator tests on
  206. // the cache.
  207. //
  208. if (S_OK == hr)
  209. {
  210. hr = TestEnumerator((void *) pEsd, sizeof(STATDATA), iSDATA, NULL, NULL,NULL);
  211. }
  212. //
  213. // Reset the enumerator before beginning our UnCache loop.
  214. //
  215. if (S_OK == hr)
  216. {
  217. hr = pEsd->Reset();
  218. }
  219. if (S_OK == hr)
  220. {
  221. //
  222. // Loop until a failure or until we have removed all of
  223. // the nodes that we thought should exist
  224. //
  225. STATDATA stat;
  226. while (S_OK == hr && iSDATA > 0)
  227. {
  228. hr = pEsd->Next(1, &stat, NULL);
  229. if (S_OK == hr)
  230. {
  231. hr = m_pOleCache->Uncache(stat.dwConnection);
  232. iSDATA--;
  233. }
  234. }
  235. }
  236. return hr;
  237. }