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.

1432 lines
39 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: cliptest.cpp
  7. //
  8. // Contents: Data Advise Holder tests
  9. //
  10. // Classes: CDataAdviseTestFormatEtc
  11. // CTestAdviseSink
  12. // CTestDaHolder
  13. //
  14. // Functions: TestPrimeFirstOnlyOnceNoData
  15. // TestPrimeFirstOnlyOnceData
  16. // DoRegisterNotifyDeregister
  17. // TestRegisterNotifyDegister
  18. // TestRegisterNotifyDegisterNoData
  19. // TestNotifyOnStop
  20. // TestNotifyOnce
  21. // CreateMassRegistration
  22. // DoMassUnadvise
  23. // TestEnumerator
  24. // LEDataAdviseHolderTest
  25. //
  26. // History: dd-mmm-yy Author Comment
  27. // 25-May-94 ricksa author
  28. //
  29. //--------------------------------------------------------------------------
  30. #include "oletest.h"
  31. #include "gendata.h"
  32. #include "genenum.h"
  33. //+-------------------------------------------------------------------------
  34. //
  35. // Class: CDataAdviseTestFormatEtc
  36. //
  37. // Purpose: Hold FORMATETC used by the data advise holder unit tests
  38. //
  39. // Interface: GetFormatEtc - get a pointer to the FORMATETC
  40. //
  41. // History: dd-mmm-yy Author Comment
  42. // 01-Jun-94 Ricksa Created
  43. //
  44. // Notes:
  45. //
  46. //--------------------------------------------------------------------------
  47. class CDataAdviseTestFormatEtc
  48. {
  49. public:
  50. CDataAdviseTestFormatEtc(void);
  51. FORMATETC * GetFormatEtc(void);
  52. private:
  53. FORMATETC _formatetc;
  54. };
  55. //+-------------------------------------------------------------------------
  56. //
  57. // Member: CDataAdviseTestFormatEtc::CDataAdviseTestFormatEtc
  58. //
  59. // Synopsis: Initialize object
  60. //
  61. // History: dd-mmm-yy Author Comment
  62. // 01-Jun-94 Ricksa Created
  63. //
  64. //--------------------------------------------------------------------------
  65. CDataAdviseTestFormatEtc::CDataAdviseTestFormatEtc(void)
  66. {
  67. _formatetc.cfFormat = RegisterClipboardFormat("OleTest Storage Format");
  68. _formatetc.ptd = NULL;
  69. _formatetc.dwAspect = DVASPECT_CONTENT;
  70. _formatetc.lindex = -1;
  71. _formatetc.tymed = TYMED_ISTORAGE;
  72. }
  73. //+-------------------------------------------------------------------------
  74. //
  75. // Member: CDataAdviseTestFormatEtc::GetFormatEtc
  76. //
  77. // Synopsis: Get pointer to standard format etc
  78. //
  79. // History: dd-mmm-yy Author Comment
  80. // 01-Jun-94 Ricksa Created
  81. //
  82. //--------------------------------------------------------------------------
  83. FORMATETC *CDataAdviseTestFormatEtc::GetFormatEtc(void)
  84. {
  85. return &_formatetc;
  86. }
  87. // Global Formatec for all the data advise tests
  88. CDataAdviseTestFormatEtc g_datfeDaTest;
  89. //+-------------------------------------------------------------------------
  90. //
  91. // Class: CTestAdviseSink
  92. //
  93. // Purpose: Advise sink used to verify data advise holder
  94. //
  95. // Interface: QueryInterface - get new interface pointer
  96. // AddRef - bump reference count
  97. // Release - decrement reference count
  98. // OnDataChange - data change notification
  99. // OnViewChange - not implemented
  100. // OnRename - not implemented
  101. // OnSave - not implemented
  102. // OnClose - not implemented
  103. // ValidOnDataChange - verify all expected data change notification
  104. //
  105. // History: dd-mmm-yy Author Comment
  106. // 01-Jun-94 Ricksa Created
  107. //
  108. // Notes: We only implement interface methods required for
  109. // test of data advise holder.
  110. //
  111. //--------------------------------------------------------------------------
  112. class CTestAdviseSink : public IAdviseSink
  113. {
  114. public:
  115. CTestAdviseSink(CGenDataObject *pgdo);
  116. // IUnknown methods
  117. STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppvObj);
  118. STDMETHOD_(ULONG, AddRef)(void);
  119. STDMETHOD_(ULONG, Release)(void);
  120. // IAdviseSink methods
  121. STDMETHOD_(void, OnDataChange)(FORMATETC *pFormatetc, STGMEDIUM *pStgmed);
  122. STDMETHOD_(void, OnViewChange)(
  123. DWORD dwAspect,
  124. LONG lindex);
  125. STDMETHOD_(void, OnRename)(IMoniker *pmk);
  126. STDMETHOD_(void, OnSave)(void);
  127. STDMETHOD_(void, OnClose)(void);
  128. // Test methods used for verification
  129. BOOL ValidOnDataChange(void);
  130. private:
  131. LONG _lRefs;
  132. CGenDataObject * _pgdo;
  133. BOOL _fValidOnDataChange;
  134. };
  135. //+-------------------------------------------------------------------------
  136. //
  137. // Member: CTestAdviseSink::CTestAdviseSink
  138. //
  139. // Synopsis: Initialize object
  140. //
  141. // Arguments: [pgdo] - generic data object
  142. //
  143. // History: dd-mmm-yy Author Comment
  144. // 01-Jun-94 Ricksa Created
  145. //
  146. // Notes: pgdo being NULL means we don't expect a STGMEDIUM when
  147. // the OnDataChange notification occurs.
  148. //
  149. //--------------------------------------------------------------------------
  150. CTestAdviseSink::CTestAdviseSink(CGenDataObject *pgdo)
  151. : _lRefs(1), _fValidOnDataChange(FALSE)
  152. {
  153. _pgdo = pgdo;
  154. }
  155. //+-------------------------------------------------------------------------
  156. //
  157. // Member: CTestAdviseSink::QueryInterface
  158. //
  159. // Synopsis: Return a new interface
  160. //
  161. // Arguments: [riid] - interface id requested
  162. // [ppvObj] - where to put the interface
  163. //
  164. // Returns: S_OK - we are returning an interface
  165. // E_NOINTERFACE - we do not support the requested interface
  166. //
  167. // History: dd-mmm-yy Author Comment
  168. // 01-Jun-94 Ricksa Created
  169. //
  170. //--------------------------------------------------------------------------
  171. STDMETHODIMP CTestAdviseSink::QueryInterface(
  172. REFIID riid,
  173. LPVOID *ppvObj)
  174. {
  175. if (IsEqualGUID(IID_IUnknown, riid) || IsEqualGUID(IID_IAdviseSink, riid))
  176. {
  177. AddRef();
  178. *ppvObj = this;
  179. return NOERROR;
  180. }
  181. *ppvObj = NULL;
  182. return E_NOINTERFACE;
  183. }
  184. //+-------------------------------------------------------------------------
  185. //
  186. // Member: CTestAdviseSink::AddRef
  187. //
  188. // Synopsis: Bump reference count
  189. //
  190. // History: dd-mmm-yy Author Comment
  191. // 01-Jun-94 Ricksa Created
  192. //
  193. //--------------------------------------------------------------------------
  194. STDMETHODIMP_(ULONG) CTestAdviseSink::AddRef(void)
  195. {
  196. return _lRefs++;
  197. }
  198. //+-------------------------------------------------------------------------
  199. //
  200. // Member: CTestAdviseSink::Release
  201. //
  202. // Synopsis: Decrement reference count
  203. //
  204. // History: dd-mmm-yy Author Comment
  205. // 01-Jun-94 Ricksa Created
  206. //
  207. //--------------------------------------------------------------------------
  208. STDMETHODIMP_(ULONG) CTestAdviseSink::Release(void)
  209. {
  210. assert(_lRefs >= 1);
  211. return --_lRefs;
  212. }
  213. //+-------------------------------------------------------------------------
  214. //
  215. // Member: CTestAdviseSink::OnDataChange
  216. //
  217. // Synopsis: Notify of change in data
  218. //
  219. // Arguments: [pFormatetc] - FORMATETC of data
  220. // [pStgmed] - storage medium for data
  221. //
  222. // Algorithm: Verify that the we recieved the expected FORMATEC. Then
  223. // verify that we recieved the expected STGMEDIUM.
  224. //
  225. // History: dd-mmm-yy Author Comment
  226. // 01-Jun-94 Ricksa Created
  227. //
  228. //--------------------------------------------------------------------------
  229. STDMETHODIMP_(void) CTestAdviseSink::OnDataChange(
  230. FORMATETC *pFormatetc,
  231. STGMEDIUM *pStgmed)
  232. {
  233. // Verify the format
  234. if (memcmp(g_datfeDaTest.GetFormatEtc(), pFormatetc, sizeof(FORMATETC))
  235. == 0)
  236. {
  237. if (_pgdo != NULL)
  238. {
  239. // We have a data object that we can use to verify the format
  240. // so we do.
  241. _fValidOnDataChange =
  242. _pgdo->VerifyFormatAndMedium(pFormatetc, pStgmed);
  243. }
  244. // We are expecting an empty STGMEDIUM so verify that it is
  245. else if ((pStgmed->tymed == TYMED_NULL)
  246. && (pStgmed->pUnkForRelease == NULL))
  247. {
  248. _fValidOnDataChange = TRUE;
  249. }
  250. }
  251. }
  252. //+-------------------------------------------------------------------------
  253. //
  254. // Member: CTestAdviseSink::OnViewChange
  255. //
  256. // Synopsis: Notify that view should change
  257. //
  258. // Arguments: [dwAspect] - specifies view of the object
  259. // [lindex] - which piece of view changed
  260. //
  261. // History: dd-mmm-yy Author Comment
  262. // 01-Jun-94 Ricksa Created
  263. //
  264. // Notes: Not supported for this object
  265. //
  266. //--------------------------------------------------------------------------
  267. STDMETHODIMP_(void) CTestAdviseSink::OnViewChange(
  268. DWORD dwAspect,
  269. LONG lindex)
  270. {
  271. OutputString("CTestAdviseSink::OnViewChange Unexpectedly Called!\r\n");
  272. }
  273. //+-------------------------------------------------------------------------
  274. //
  275. // Member: CTestAdviseSink::OnRename
  276. //
  277. // Synopsis: Notifies of rename operation
  278. //
  279. // History: dd-mmm-yy Author Comment
  280. // 01-Jun-94 Ricksa Created
  281. //
  282. // Notes: Not supported for this object
  283. //
  284. //--------------------------------------------------------------------------
  285. STDMETHODIMP_(void) CTestAdviseSink::OnRename(IMoniker *pmk)
  286. {
  287. OutputString("CTestAdviseSink::OnRename Unexpectedly Called!\r\n");
  288. }
  289. //+-------------------------------------------------------------------------
  290. //
  291. // Member: CTestAdviseSink::OnSave
  292. //
  293. // Synopsis: Notify that object was saved
  294. //
  295. // History: dd-mmm-yy Author Comment
  296. // 01-Jun-94 Ricksa Created
  297. //
  298. // Notes: Not supported for this object
  299. //
  300. //--------------------------------------------------------------------------
  301. STDMETHODIMP_(void) CTestAdviseSink::OnSave(void)
  302. {
  303. OutputString("CTestAdviseSink::OnSave Unexpectedly Called!\r\n");
  304. }
  305. //+-------------------------------------------------------------------------
  306. //
  307. // Member: CTestAdviseSink::OnClose
  308. //
  309. // Synopsis: Notify object closed
  310. //
  311. // History: dd-mmm-yy Author Comment
  312. // 01-Jun-94 Ricksa Created
  313. //
  314. // Notes: Not supported for this object
  315. //
  316. //--------------------------------------------------------------------------
  317. STDMETHODIMP_(void) CTestAdviseSink::OnClose(void)
  318. {
  319. OutputString("CTestAdviseSink::OnClose Unexpectedly Called!\r\n");
  320. }
  321. //+-------------------------------------------------------------------------
  322. //
  323. // Member: CTestAdviseSink::ValidOnDataChange
  324. //
  325. // Synopsis: Verify that we recieved the expected OnDataChange notification
  326. //
  327. // History: dd-mmm-yy Author Comment
  328. // 01-Jun-94 Ricksa Created
  329. //
  330. //--------------------------------------------------------------------------
  331. BOOL CTestAdviseSink::ValidOnDataChange(void)
  332. {
  333. BOOL fResult = _fValidOnDataChange;
  334. _fValidOnDataChange = FALSE;
  335. return fResult;
  336. }
  337. // Preallocated structure used to mass advise registration testing
  338. #define MAX_REGISTER 100
  339. struct
  340. {
  341. CTestAdviseSink * ptas;
  342. DWORD dwConnection;
  343. } aMassAdvise[MAX_REGISTER];
  344. //+-------------------------------------------------------------------------
  345. //
  346. // Class: CTestDaHolder
  347. //
  348. // Purpose: Test enumerator for data advise holder
  349. //
  350. // Interface: Verify - verify particular entry being enumerated
  351. // VerifyAllEnmerated - verify all entries were enumerated once
  352. //
  353. // History: dd-mmm-yy Author Comment
  354. // 01-Jun-94 Ricksa Created
  355. //
  356. //--------------------------------------------------------------------------
  357. class CTestDaHolder : public CEnumeratorTest
  358. {
  359. public:
  360. CTestDaHolder(IEnumSTATDATA *penumAdvise, HRESULT& rhr);
  361. BOOL Verify(void *);
  362. BOOL VerifyAllEnmerated(void);
  363. BOOL VerifyAll(void *, LONG);
  364. private:
  365. DWORD _cdwFound[MAX_REGISTER];
  366. };
  367. //+-------------------------------------------------------------------------
  368. //
  369. // Member: CTestDaHolder::CTestDaHolder
  370. //
  371. // Synopsis: Initialize object
  372. //
  373. // Arguments: [penumAdvise] - data advise holder enumerator
  374. // [rhr] - HRESULT reference thorugh which to return an error
  375. //
  376. // Algorithm:
  377. //
  378. // History: dd-mmm-yy Author Comment
  379. // 01-Jun-94 Ricksa Created
  380. //
  381. //--------------------------------------------------------------------------
  382. CTestDaHolder::CTestDaHolder(IEnumSTATDATA *penumAdvise, HRESULT& rhr)
  383. : CEnumeratorTest(penumAdvise, sizeof(STATDATA), MAX_REGISTER, rhr)
  384. {
  385. // Zero out our table of counts
  386. memset(&_cdwFound[0], 0, sizeof(_cdwFound));
  387. }
  388. //+-------------------------------------------------------------------------
  389. //
  390. // Member: CTestDaHolder::VerifyAllEnmerated
  391. //
  392. // Synopsis: Verify all objects got enumerated
  393. //
  394. // Returns: TRUE - all objects enumerated
  395. // FALSE - error in enumeration
  396. //
  397. // History: dd-mmm-yy Author Comment
  398. // 01-Jun-94 Ricksa Created
  399. //
  400. //--------------------------------------------------------------------------
  401. BOOL CTestDaHolder::VerifyAllEnmerated(void)
  402. {
  403. for (int i = 0; i < MAX_REGISTER; i++)
  404. {
  405. if (_cdwFound[i] != 1)
  406. {
  407. OutputString("Entry %d enumerated %d times\r\n", i, _cdwFound[i]);
  408. return FALSE;
  409. }
  410. // Reset for another test
  411. _cdwFound[i] = 0;
  412. }
  413. return TRUE;
  414. }
  415. //+-------------------------------------------------------------------------
  416. //
  417. // Member: CTestDaHolder::Verify
  418. //
  419. // Synopsis: Verify an enumeration entry
  420. //
  421. // Arguments: [pvEntry] - entry enumerated
  422. //
  423. // Returns: TRUE - enumerated entry is valid
  424. // FALSE - obvious error in enumeration
  425. //
  426. // History: dd-mmm-yy Author Comment
  427. // 01-Jun-94 Ricksa Created
  428. //
  429. //--------------------------------------------------------------------------
  430. BOOL CTestDaHolder::Verify(void *pvEntry)
  431. {
  432. STATDATA *pstatdata = (STATDATA *) pvEntry;
  433. // Verify the advf field
  434. if ((pstatdata->advf == 0)
  435. && (memcmp(g_datfeDaTest.GetFormatEtc(), &pstatdata->formatetc,
  436. sizeof(FORMATETC)) == 0))
  437. {
  438. // Can we find the connection?
  439. for (int i = 0; i < MAX_REGISTER; i++)
  440. {
  441. if (pstatdata->dwConnection == aMassAdvise[i].dwConnection)
  442. {
  443. // Bump found count
  444. _cdwFound[i]++;
  445. // Everything is OK so tell the caller
  446. return TRUE;
  447. }
  448. }
  449. }
  450. return FALSE;
  451. }
  452. //+-------------------------------------------------------------------------
  453. //
  454. // Member: CTestDaHolder::VerifyAll
  455. //
  456. // Synopsis: Verify that an array of all entries is valid
  457. //
  458. // Arguments: [pvEntries] - array of enumerated data
  459. // [clEntries] - number of enumerated entries
  460. //
  461. // Returns: TRUE - enumerated entry is valid
  462. // FALSE - obvious error in enumeration
  463. //
  464. // History: dd-mmm-yy Author Comment
  465. // 02-Jun-94 Ricksa Created
  466. //
  467. //--------------------------------------------------------------------------
  468. BOOL CTestDaHolder::VerifyAll(void *pvEntries, LONG clEntries)
  469. {
  470. // Verify that the count is as expected.
  471. if (clEntries != MAX_REGISTER)
  472. {
  473. return FALSE;
  474. }
  475. // Verify each entry in the array is reasonable
  476. STATDATA *pstatdata = (STATDATA *) pvEntries;
  477. for (int i = 0; i < MAX_REGISTER; i++, pstatdata++)
  478. {
  479. if (!Verify(pstatdata))
  480. {
  481. return FALSE;
  482. }
  483. }
  484. // Verify that each entry was only referred to once
  485. return VerifyAllEnmerated();
  486. }
  487. //+-------------------------------------------------------------------------
  488. //
  489. // Function: TestPrimeFirstOnlyOnceNoData
  490. //
  491. // Synopsis: Test one notification of
  492. // ADVF_NODATA | ADVF_PRIMEFIRST | ADVF_ONLYONCE
  493. //
  494. // Arguments: [pdahTest] - data advise holder we are testing
  495. // [pgdo] - generic data object
  496. //
  497. // Returns: NOERROR - notification was correct
  498. // E_FAIL - error in notification
  499. //
  500. // Algorithm: Create an test advise sink object. Register it with the
  501. // advise holder which should cause the notification. Verify
  502. // that the advise was notified and that no connection was
  503. // returned.
  504. //
  505. // History: dd-mmm-yy Author Comment
  506. // 01-Jun-94 Ricksa Created
  507. //
  508. //--------------------------------------------------------------------------
  509. HRESULT TestPrimeFirstOnlyOnceNoData(
  510. IDataAdviseHolder *pdahTest,
  511. CGenDataObject *pgdo)
  512. {
  513. // Create an advise sink - the NULL means we don't want to validate
  514. // the STGMEDIUM.
  515. CTestAdviseSink tas(NULL);
  516. DWORD dwConnection = 0;
  517. // Register the advise
  518. HRESULT hr = pdahTest->Advise(pgdo, g_datfeDaTest.GetFormatEtc(),
  519. ADVF_NODATA | ADVF_PRIMEFIRST | ADVF_ONLYONCE, &tas, &dwConnection);
  520. // Confirm that the advise is notified and in the correct state
  521. if (!tas.ValidOnDataChange())
  522. {
  523. OutputString("TestPrimeFirstOnlyOnceNoData OnDataChange invalid!\r\n");
  524. return E_FAIL;
  525. }
  526. // Make sure the advise was not registered
  527. if (dwConnection != 0)
  528. {
  529. OutputString("TestPrimeFirstOnlyOnceNoData got Connection!\r\n");
  530. return E_FAIL;
  531. }
  532. return NOERROR;
  533. }
  534. //+-------------------------------------------------------------------------
  535. //
  536. // Function: TestPrimeFirstOnlyOnceData
  537. //
  538. // Synopsis: Test one notification of
  539. // ADVF_PRIMEFIRST | ADVF_ONLYONCE
  540. //
  541. // Arguments: [pdahTest] - data advise holder we are testing
  542. // [pgdo] - generic data object
  543. //
  544. // Returns: NOERROR - notification was correct
  545. // E_FAIL - error in notification
  546. //
  547. // Algorithm: Create an test advise sink object. Register it with the
  548. // advise holder which should cause the notification. Verify
  549. // that the advise was notified and that no connection was
  550. // returned.
  551. //
  552. // History: dd-mmm-yy Author Comment
  553. // 01-Jun-94 Ricksa Created
  554. //
  555. //--------------------------------------------------------------------------
  556. HRESULT TestPrimeFirstOnlyOnceData(
  557. IDataAdviseHolder *pdahTest,
  558. CGenDataObject *pgdo)
  559. {
  560. // Create an advise sink that we can verify the STGMEDIUM
  561. CTestAdviseSink tas(pgdo);
  562. // Where to store the connection
  563. DWORD dwConnection = 0;
  564. // Register the advise
  565. HRESULT hr = pdahTest->Advise(pgdo, g_datfeDaTest.GetFormatEtc(),
  566. ADVF_PRIMEFIRST | ADVF_ONLYONCE, &tas, &dwConnection);
  567. // Confirm that the advise is notified and in the correct state
  568. if (!tas.ValidOnDataChange())
  569. {
  570. OutputString("TestPrimeFirstOnlyOnceData OnDataChange invalid!\r\n");
  571. return E_FAIL;
  572. }
  573. // Make sure the advise was not registered
  574. if (dwConnection != 0)
  575. {
  576. OutputString("TestPrimeFirstOnlyOnceData got Connection!\r\n");
  577. return E_FAIL;
  578. }
  579. return NOERROR;
  580. }
  581. //+-------------------------------------------------------------------------
  582. //
  583. // Function: DoRegisterNotifyDeregister
  584. //
  585. // Synopsis:
  586. //
  587. // Arguments: [pdahTest] - data advise holder we are testing
  588. // [pdo] - IDataObject interface
  589. // [pgdo] - generic data object
  590. // [advf] - advise flags to use
  591. // [pszCaller] - name of test
  592. //
  593. // Returns: NOERROR - notification was correct
  594. // E_FAIL - error in notification
  595. //
  596. // Algorithm: Create a test advise sink object. Register for an notification
  597. // with the data advise holder. Confirm that the prime first
  598. // notification worked. Confirm that the object did get
  599. // registered. Tell the advise holder to notify all registered
  600. // advises that the data changed. Confirm that the appropriate
  601. // notification was sent. Then deregister the advise. Do it
  602. // again to make sure the connection is no longer valid.
  603. //
  604. // History: dd-mmm-yy Author Comment
  605. // 01-Jun-94 Ricksa Created
  606. //
  607. //--------------------------------------------------------------------------
  608. HRESULT DoRegisterNotifyDeregister(
  609. IDataAdviseHolder *pdahTest,
  610. IDataObject *pdo,
  611. CGenDataObject *pgdo,
  612. DWORD advf,
  613. char *pszCaller)
  614. {
  615. // Create an advise sink that we can verify the STGMEDIUM
  616. CTestAdviseSink tas(pgdo);
  617. // Where to store the connection
  618. DWORD dwConnection;
  619. // Register the advise
  620. HRESULT hr = pdahTest->Advise(pdo, g_datfeDaTest.GetFormatEtc(),
  621. ADVF_PRIMEFIRST | advf, &tas, &dwConnection);
  622. // Confirm that the advise is notified and in the correct state
  623. if (!tas.ValidOnDataChange())
  624. {
  625. OutputString("%s First OnDataChange invalid!\r\n", pszCaller);
  626. return E_FAIL;
  627. }
  628. // Make sure the advise is registered
  629. if (dwConnection == 0)
  630. {
  631. OutputString("%s did not get Connection!\r\n", pszCaller);
  632. return E_FAIL;
  633. }
  634. // Test regular data change
  635. hr = pdahTest->SendOnDataChange(pdo, 0, 0);
  636. if (hr != NOERROR)
  637. {
  638. OutputString("%s SendOnDataChange unexpected HRESULT = %lx!\r\n",
  639. pszCaller, hr);
  640. return E_FAIL;
  641. }
  642. // Confirm that the advise is notified and in the correct state
  643. if (!tas.ValidOnDataChange())
  644. {
  645. OutputString("%s Second OnDataChange invalid!\r\n", pszCaller);
  646. return E_FAIL;
  647. }
  648. // Test unadvise
  649. hr = pdahTest->Unadvise(dwConnection);
  650. if (hr != NOERROR)
  651. {
  652. OutputString("%s Unadvise unexpected HRESULT = %lx!\r\n", pszCaller, hr);
  653. return E_FAIL;
  654. }
  655. // Test second unadvise on the same connection
  656. hr = pdahTest->Unadvise(dwConnection);
  657. if (hr != OLE_E_NOCONNECTION)
  658. {
  659. OutputString("%s Second Unadvise Bad Hresult = %lx!\r\n", pszCaller, hr);
  660. return E_FAIL;
  661. }
  662. return NOERROR;
  663. }
  664. //+-------------------------------------------------------------------------
  665. //
  666. // Function: TestRegisterNotifyDegister
  667. //
  668. // Synopsis: Test a simple register/notify/deregister sequence
  669. //
  670. // Arguments: [pdahTest] - data advise holder we are testing
  671. // [pgdo] - generic data object
  672. //
  673. // Returns: NOERROR - notification was correct
  674. // E_FAIL - error in notification
  675. //
  676. // History: dd-mmm-yy Author Comment
  677. // 01-Jun-94 Ricksa Created
  678. //
  679. //--------------------------------------------------------------------------
  680. HRESULT TestRegisterNotifyDegister(
  681. IDataAdviseHolder *pdahTest,
  682. CGenDataObject *pgdo)
  683. {
  684. return DoRegisterNotifyDeregister(pdahTest, pgdo, pgdo, 0,
  685. "TestRegisterNotifyDegister");
  686. }
  687. //+-------------------------------------------------------------------------
  688. //
  689. // Function: TestRegisterNotifyDegisterNoData
  690. //
  691. // Synopsis: Test a simple register/notify/deregister sequence with
  692. // no data being returned.
  693. //
  694. // Arguments: [pdahTest] - data advise holder we are testing
  695. // [pgdo] - generic data object
  696. //
  697. // Returns: NOERROR - notification was correct
  698. // E_FAIL - error in notification
  699. //
  700. // History: dd-mmm-yy Author Comment
  701. // 01-Jun-94 Ricksa Created
  702. //
  703. //--------------------------------------------------------------------------
  704. HRESULT TestRegisterNotifyDegisterNoData(
  705. IDataAdviseHolder *pdahTest,
  706. CGenDataObject *pgdo)
  707. {
  708. return DoRegisterNotifyDeregister(pdahTest, pgdo, NULL, ADVF_NODATA,
  709. "TestRegisterNotifyDegisterNoData");
  710. }
  711. //+-------------------------------------------------------------------------
  712. //
  713. // Function: TestNotifyOnStop
  714. //
  715. // Synopsis: Test a registration with a call of notify on stop
  716. //
  717. // Arguments: [pdahTest] - data advise holder we are testing
  718. // [pgdo] - generic data object
  719. //
  720. // Returns: NOERROR - notification was correct
  721. // E_FAIL - error in notification
  722. //
  723. // Algorithm: Create a test object. Register it with the advise holder.
  724. // Confirm that the connection was returned and that no
  725. // notification occurred. Then tell the data advise holder
  726. // to notify its registrations of a data change. Make sure
  727. // that the advise was correctly notified. Finally, verify
  728. // that we can deregister the advise and that its connection
  729. // becomes invalid.
  730. //
  731. // History: dd-mmm-yy Author Comment
  732. // 01-Jun-94 Ricksa Created
  733. //
  734. //--------------------------------------------------------------------------
  735. HRESULT TestNotifyOnStop(
  736. IDataAdviseHolder *pdahTest,
  737. CGenDataObject *pgdo)
  738. {
  739. // Routine name for messages
  740. char *pszCaller = "TestNotifyOnStop";
  741. // Create an advise sink that we can verify the STGMEDIUM
  742. CTestAdviseSink tas(pgdo);
  743. // Where to store the connection
  744. DWORD dwConnection;
  745. // Register the advise
  746. HRESULT hr = pdahTest->Advise(pgdo, g_datfeDaTest.GetFormatEtc(),
  747. ADVF_DATAONSTOP, &tas, &dwConnection);
  748. // Make sure the advise is registered
  749. if (dwConnection == 0)
  750. {
  751. OutputString("%s did not get Connection!\r\n", pszCaller);
  752. return E_FAIL;
  753. }
  754. // Confirm that the data object was not notified
  755. if (tas.ValidOnDataChange())
  756. {
  757. OutputString("%s Registration caused notification!\r\n", pszCaller);
  758. return E_FAIL;
  759. }
  760. // Test regular data change
  761. hr = pdahTest->SendOnDataChange(pgdo, 0, ADVF_DATAONSTOP);
  762. if (hr != NOERROR)
  763. {
  764. OutputString("%s SendOnDataChange unexpected HRESULT = %lx!\r\n",
  765. pszCaller, hr);
  766. return E_FAIL;
  767. }
  768. // Confirm that the advise is notified and in the correct state
  769. if (!tas.ValidOnDataChange())
  770. {
  771. OutputString("%s Second OnDataChange invalid!\r\n", pszCaller);
  772. return E_FAIL;
  773. }
  774. // Test unadvise
  775. hr = pdahTest->Unadvise(dwConnection);
  776. if (hr != NOERROR)
  777. {
  778. OutputString("%s Unadvise unexpected HRESULT = %lx!\r\n", pszCaller, hr);
  779. return E_FAIL;
  780. }
  781. // Test second unadvise on the same connection
  782. hr = pdahTest->Unadvise(dwConnection);
  783. if (hr != OLE_E_NOCONNECTION)
  784. {
  785. OutputString("%s Second Unadvise Bad Hresult = %lx!\r\n", pszCaller, hr);
  786. return E_FAIL;
  787. }
  788. return NOERROR;
  789. }
  790. //+-------------------------------------------------------------------------
  791. //
  792. // Function: TestNotifyOnce
  793. //
  794. // Synopsis: Test a notify once advise
  795. //
  796. // Arguments: [pdahTest] - data advise holder we are testing
  797. // [pgdo] - generic data object
  798. //
  799. // Returns: NOERROR - notification was correct
  800. // E_FAIL - error in notification
  801. //
  802. // Algorithm: Create a test advise object. Register it to be advised only
  803. // once of a change. Confirm that we got a registration. Then
  804. // tell the advise holder to notify its advises of a data
  805. // change. Confirm that the correct notification occurred. Finally,
  806. // confirm that we are no longer registered with the advise
  807. // holder.
  808. //
  809. // History: dd-mmm-yy Author Comment
  810. // 01-Jun-94 Ricksa Created
  811. //
  812. //--------------------------------------------------------------------------
  813. HRESULT TestNotifyOnce(
  814. IDataAdviseHolder *pdahTest,
  815. CGenDataObject *pgdo)
  816. {
  817. // Routine name for messages
  818. char *pszCaller = "TestNotifyOnce";
  819. // Create an advise sink that we can verify the STGMEDIUM
  820. CTestAdviseSink tas(pgdo);
  821. // Where to store the connection
  822. DWORD dwConnection;
  823. // Register the advise
  824. HRESULT hr = pdahTest->Advise(pgdo, g_datfeDaTest.GetFormatEtc(),
  825. ADVF_ONLYONCE, &tas, &dwConnection);
  826. // Make sure the advise is registered
  827. if (dwConnection == 0)
  828. {
  829. OutputString("%s did not get Connection!\r\n", pszCaller);
  830. return E_FAIL;
  831. }
  832. // Test regular data change
  833. hr = pdahTest->SendOnDataChange(pgdo, 0, 0);
  834. if (hr != NOERROR)
  835. {
  836. OutputString("%s SendOnDataChange unexpected HRESULT = %lx!\r\n",
  837. pszCaller, hr);
  838. return E_FAIL;
  839. }
  840. // Confirm that the advise is notified and in the correct state
  841. if (!tas.ValidOnDataChange())
  842. {
  843. OutputString("%s Send OnDataChange invalid!\r\n", pszCaller);
  844. return E_FAIL;
  845. }
  846. // Try a second notify
  847. hr = pdahTest->SendOnDataChange(pgdo, 0, 0);
  848. // Confirm that the advise is *not* notified
  849. if (tas.ValidOnDataChange())
  850. {
  851. OutputString("%s Second OnDataChange unexpectedly succeeded!\r\n",
  852. pszCaller);
  853. return E_FAIL;
  854. }
  855. // Test unadvise - should fail since we requested to be notified
  856. // only once.
  857. hr = pdahTest->Unadvise(dwConnection);
  858. if (hr != OLE_E_NOCONNECTION)
  859. {
  860. OutputString("%s Second Unadvise Bad Hresult = %lx!\r\n", pszCaller, hr);
  861. return E_FAIL;
  862. }
  863. return NOERROR;
  864. }
  865. //+-------------------------------------------------------------------------
  866. //
  867. // Function: CreateMassRegistration
  868. //
  869. // Synopsis: Register a large number of advise objects with a holder
  870. //
  871. // Arguments: [pdahTest] - data advise holder we are testing
  872. // [pgdo] - generic data object
  873. // [pszCaller] - name of test
  874. //
  875. // Returns: NOERROR - all advises were registered
  876. // E_FAIL - error in registration
  877. //
  878. // Algorithm: Create a MAX_REGISTER number of test advise objects and
  879. // store them in the aMassAdvise array. Then register them
  880. // all with the input advise holder.
  881. //
  882. // History: dd-mmm-yy Author Comment
  883. // 01-Jun-94 Ricksa Created
  884. //
  885. //--------------------------------------------------------------------------
  886. HRESULT CreateMassRegistration(
  887. IDataAdviseHolder *pdahTest,
  888. CGenDataObject *pgdo,
  889. char *pszCaller)
  890. {
  891. // Create the advise sinks for the test for the test
  892. for (int i = 0; i < MAX_REGISTER; i++)
  893. {
  894. aMassAdvise[i].ptas = new CTestAdviseSink(pgdo);
  895. if (aMassAdvise[i].ptas == NULL)
  896. {
  897. OutputString(
  898. "%s Advise create of test advise failed on %d!\r\n", pszCaller,
  899. i);
  900. return E_FAIL;
  901. }
  902. aMassAdvise[i].dwConnection = 0;
  903. }
  904. HRESULT hr;
  905. // Register the advise sinks
  906. for (i = 0; i < MAX_REGISTER; i++)
  907. {
  908. // Register the advise
  909. hr = pdahTest->Advise(pgdo, g_datfeDaTest.GetFormatEtc(),
  910. 0, aMassAdvise[i].ptas, &aMassAdvise[i].dwConnection);
  911. if (hr != NOERROR)
  912. {
  913. OutputString(
  914. "%s Advise unexpected HRESULT = %lx on %d!\r\n", pszCaller,
  915. hr, i);
  916. return E_FAIL;
  917. }
  918. }
  919. return S_OK;
  920. }
  921. //+-------------------------------------------------------------------------
  922. //
  923. // Function: DoMassUnadvise
  924. //
  925. // Synopsis: Deregister all entries in the aMassAdvise array
  926. //
  927. // Arguments: [pdahTest] - data advise holder we are testing
  928. // [pszCaller] - name of test
  929. //
  930. // Returns: NOERROR - deregistration worked
  931. // E_FAIL - error in deregistration
  932. //
  933. // Algorithm: For each entry in the aMassAdvise array, deregister it
  934. // from the holder. Then confirm that its connection is
  935. // no longer valid.
  936. //
  937. // History: dd-mmm-yy Author Comment
  938. // 01-Jun-94 Ricksa Created
  939. //
  940. //--------------------------------------------------------------------------
  941. HRESULT DoMassUnadvise(
  942. IDataAdviseHolder *pdahTest,
  943. char *pszCaller)
  944. {
  945. HRESULT hr;
  946. // Unadvise them
  947. for (int i = 0; i < MAX_REGISTER; i++)
  948. {
  949. // Test unadvise
  950. hr = pdahTest->Unadvise(aMassAdvise[i].dwConnection);
  951. if (hr != NOERROR)
  952. {
  953. OutputString(
  954. "%s Unadvise unexpected HRESULT = %lx on %d!\r\n", pszCaller,
  955. hr, i);
  956. return E_FAIL;
  957. }
  958. // Test second unadvise on the same connection
  959. hr = pdahTest->Unadvise(aMassAdvise[i].dwConnection);
  960. if (hr != OLE_E_NOCONNECTION)
  961. {
  962. OutputString(
  963. "%s Second Unadvise Bad Hresult = %lx on %d!\r\n", pszCaller,
  964. hr, i);
  965. return E_FAIL;
  966. }
  967. }
  968. // Delete the advise sinks for the test
  969. for (i = 0; i < MAX_REGISTER; i++)
  970. {
  971. delete aMassAdvise[i].ptas ;
  972. }
  973. return S_OK;
  974. }
  975. //+-------------------------------------------------------------------------
  976. //
  977. // Function: TestMassRegister
  978. //
  979. // Synopsis: Test registering a large number of advises with a holder
  980. //
  981. // Arguments: [pdahTest] - data advise holder we are testing
  982. // [pgdo] - generic data object
  983. //
  984. // Returns: NOERROR - notification was correct
  985. // E_FAIL - error in notification
  986. //
  987. // Algorithm: Register a large number of test advises with the data advise
  988. // holder. Then tell the advise holder to notify them of
  989. // a change. Confirm that all registered entries were notified.
  990. // Finally, deregister all the test advises.
  991. //
  992. // History: dd-mmm-yy Author Comment
  993. // 01-Jun-94 Ricksa Created
  994. //
  995. //--------------------------------------------------------------------------
  996. HRESULT TestMassRegister(
  997. IDataAdviseHolder *pdahTest,
  998. CGenDataObject *pgdo)
  999. {
  1000. char *pszCaller = "TestMassRegister";
  1001. HRESULT hr = CreateMassRegistration(pdahTest, pgdo, "TestMassRegister");
  1002. if (hr != NOERROR)
  1003. {
  1004. return hr;
  1005. }
  1006. // Notify them of a change
  1007. hr = pdahTest->SendOnDataChange(pgdo, 0, 0);
  1008. // Verify that each was notified
  1009. for (int i = 0; i < MAX_REGISTER; i++)
  1010. {
  1011. if (!aMassAdvise[i].ptas->ValidOnDataChange())
  1012. {
  1013. OutputString(
  1014. "%s OnDataChange invalid for entry %d!\r\n", pszCaller, i);
  1015. return E_FAIL;
  1016. }
  1017. }
  1018. // Unadvise them and free the memory
  1019. return DoMassUnadvise(pdahTest, "TestMassRegister");
  1020. }
  1021. //+-------------------------------------------------------------------------
  1022. //
  1023. // Function: TestEnumerator
  1024. //
  1025. // Synopsis: Test the data advise holder enumerator
  1026. //
  1027. // Arguments: [pdahTest] - data advise holder we are testing
  1028. // [pgdo] - generic data object
  1029. //
  1030. // Returns: NOERROR - notification was correct
  1031. // E_FAIL - error in notification
  1032. //
  1033. // Algorithm: Create a large number of test advises and register them
  1034. // with the advise holder. Get an advise enumerator. Create
  1035. // a test enumerator object. Tell the test enumerator object
  1036. // to enumerate all the object in the holder. Verify that
  1037. // all objects were correctly enumerated. Then release the
  1038. // advise holder enumerator. Finally, deregister all the
  1039. // test advises from the advise holder.
  1040. //
  1041. // History: dd-mmm-yy Author Comment
  1042. // 01-Jun-94 Ricksa Created
  1043. //
  1044. //--------------------------------------------------------------------------
  1045. HRESULT TestEnumerator(
  1046. IDataAdviseHolder *pdahTest,
  1047. CGenDataObject *pgdo)
  1048. {
  1049. char *pszCaller = "TestEnumerator";
  1050. // Do a mass register
  1051. HRESULT hr = CreateMassRegistration(pdahTest, pgdo, pszCaller);
  1052. if (hr != NOERROR)
  1053. {
  1054. return hr;
  1055. }
  1056. // Get an enumerator for this registration
  1057. IEnumSTATDATA *penumAdvise;
  1058. hr = pdahTest->EnumAdvise(&penumAdvise);
  1059. if (hr != NOERROR)
  1060. {
  1061. OutputString("%s EnumAdvise failed %lx!\r\n", pszCaller, hr);
  1062. return E_FAIL;
  1063. }
  1064. // Create a test enumerator object
  1065. CTestDaHolder tdh(penumAdvise, hr);
  1066. if (hr != NOERROR)
  1067. {
  1068. OutputString(
  1069. "%s Failed creating CTestDaHolder %lx!\r\n", pszCaller, hr);
  1070. return E_FAIL;
  1071. }
  1072. // Enmerate all 1 by 1
  1073. if (tdh.TestNext() != NOERROR)
  1074. {
  1075. OutputString(
  1076. "%s tdh.TestNext failed during enumeration\r\n", pszCaller);
  1077. return E_FAIL;
  1078. }
  1079. // Verify that all entries were enumerated
  1080. if (!tdh.VerifyAllEnmerated())
  1081. {
  1082. OutputString(
  1083. "%s tdh.VerifyAllEnmerated failed verification pass\r\n", pszCaller);
  1084. return E_FAIL;
  1085. }
  1086. // Do a test all
  1087. if (tdh.TestAll() != NOERROR)
  1088. {
  1089. OutputString(
  1090. "%s tdh.TestAll failed during enumeration\r\n", pszCaller);
  1091. return E_FAIL;
  1092. }
  1093. // Release the advise enumerator
  1094. if (penumAdvise->Release() != 0)
  1095. {
  1096. OutputString(
  1097. "%s Failed freeing advise enumerator %lx!\r\n", pszCaller, hr);
  1098. return E_FAIL;
  1099. }
  1100. // Release the registrations
  1101. return DoMassUnadvise(pdahTest, pszCaller);
  1102. }
  1103. //+-------------------------------------------------------------------------
  1104. //
  1105. // Function: LEDataAdviseHolderTest
  1106. //
  1107. // Synopsis: Unit test for the data advise holder.
  1108. //
  1109. // Returns: NOERROR - test passed
  1110. // E_FAIL - test failed.
  1111. //
  1112. // Algorithm: Create an advise holder object. Run through all the test
  1113. // cases. Return NOERROR if they succeed or stop with the first
  1114. // that fails.
  1115. //
  1116. // History: dd-mmm-yy Author Comment
  1117. // 01-Jun-94 Ricksa Created
  1118. //
  1119. //--------------------------------------------------------------------------
  1120. HRESULT LEDataAdviseHolderTest(void)
  1121. {
  1122. // Create a data object for use in the test
  1123. CGenDataObject *pgdo = new CGenDataObject;
  1124. assert(pgdo);
  1125. // Create a data advise holder
  1126. IDataAdviseHolder *pdahTest;
  1127. HRESULT hr = CreateDataAdviseHolder(&pdahTest);
  1128. if (hr != NOERROR)
  1129. {
  1130. OutputString(
  1131. "LEDataAdviseHolderTest CreateDataAdviseHolder Faild hr = %lx", hr);
  1132. return hr;
  1133. }
  1134. // Case 1: ADVF_PRIMEFIRST & ADVF_ONLYONCE & ADVF_NODATA
  1135. if ((hr = TestPrimeFirstOnlyOnceNoData(pdahTest, pgdo)) != NOERROR)
  1136. {
  1137. return hr;
  1138. }
  1139. // Case 2: ADVF_PRIMEFIRST
  1140. if ((hr = TestPrimeFirstOnlyOnceNoData(pdahTest, pgdo)) != NOERROR)
  1141. {
  1142. return hr;
  1143. }
  1144. // Case 3: Register/Notify/Deregister
  1145. if ((hr = TestRegisterNotifyDegister(pdahTest, pgdo)) != NOERROR)
  1146. {
  1147. return hr;
  1148. }
  1149. // Case 4: Register/Notify/Deregister with no data returned
  1150. if ((hr = TestRegisterNotifyDegisterNoData(pdahTest, pgdo)) != NOERROR)
  1151. {
  1152. return hr;
  1153. }
  1154. // Case 5: Test notify on stop
  1155. if ((hr = TestNotifyOnStop(pdahTest, pgdo)) != NOERROR)
  1156. {
  1157. return hr;
  1158. }
  1159. // Case 6: Test notify only once
  1160. if ((hr = TestNotifyOnce(pdahTest, pgdo)) != NOERROR)
  1161. {
  1162. return hr;
  1163. }
  1164. // Case 7: Test mass Register/Notify/Deregister
  1165. if ((hr = TestMassRegister(pdahTest, pgdo)) != NOERROR)
  1166. {
  1167. return hr;
  1168. }
  1169. // Case 8: Test Enumerator
  1170. if ((hr = TestEnumerator(pdahTest, pgdo)) != NOERROR)
  1171. {
  1172. return hr;
  1173. }
  1174. // We are done
  1175. DWORD dwFinalRefs = pdahTest->Release();
  1176. if (dwFinalRefs != 0)
  1177. {
  1178. OutputString(
  1179. "LEDataAdviseHolderTest Final Release is = %d", dwFinalRefs);
  1180. return E_FAIL;
  1181. }
  1182. pgdo->Release();
  1183. return NOERROR;
  1184. }