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.

793 lines
25 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: tests.cxx
  7. //
  8. // Contents: DRT tests
  9. //
  10. // History: 23-Sep-92 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include "headers.cxx"
  14. #pragma hdrstop
  15. #include "tests.hxx"
  16. #include "ilb.hxx"
  17. void t_create(void)
  18. {
  19. WStorage *pstgRoot, *pstgChild, *pstgChild2;
  20. WStream *pstm;
  21. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  22. 0, &pstgRoot);
  23. pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, 0,
  24. &pstgChild);
  25. pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0, 0,
  26. &pstgChild2);
  27. pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0,
  28. &pstm);
  29. pstm->Unwrap();
  30. pstgChild2->Commit(0);
  31. pstgChild2->Unwrap();
  32. pstgChild->Commit(0);
  33. pstgChild->Unwrap();
  34. VerifyStructure(pstgRoot->GetI(), "dChild(dChild2(sStream))");
  35. pstgRoot->Unwrap();
  36. }
  37. void t_open(void)
  38. {
  39. WStorage *pstgRoot, *pstgChild, *pstgChild2;
  40. WStream *pstm;
  41. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  42. 0, &pstgRoot);
  43. CreateStructure(pstgRoot->GetI(), "dChild(dChild2(sStream))");
  44. pstgRoot->Commit(0);
  45. pstgRoot->Unwrap();
  46. WStgOpenStorage(DRTDF, NULL, ROOTP(WSTG_READWRITE), NULL,
  47. 0, &pstgRoot);
  48. pstgRoot->OpenStorage(STR("Child"), NULL, STGP(WSTG_READWRITE), NULL, 0,
  49. &pstgChild);
  50. pstgChild->OpenStorage(STR("Child2"), NULL, STGP(WSTG_READWRITE), NULL, 0,
  51. &pstgChild2);
  52. pstgChild2->OpenStream(STR("Stream"), NULL, STMP(WSTG_READWRITE), 0,
  53. &pstm);
  54. pstm->Unwrap();
  55. pstgChild2->Unwrap();
  56. pstgChild->Unwrap();
  57. pstgRoot->Unwrap();
  58. }
  59. void t_addref(void)
  60. {
  61. WStorage *pstg;
  62. WStream *pstm;
  63. ULONG ul;
  64. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  65. 0, &pstg);
  66. pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  67. #ifndef FLAT
  68. if ((ul = pstm->AddRef()) != 2)
  69. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  70. if ((ul = pstm->Release()) != 1)
  71. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  72. pstm->Unwrap();
  73. if ((ul = pstg->AddRef()) != 2)
  74. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  75. if ((ul = pstg->Release()) != 1)
  76. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  77. #else
  78. if ((ul = pstm->AddRef()) <= 0)
  79. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  80. if ((ul = pstm->Release()) <= 0)
  81. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  82. pstm->Unwrap();
  83. if ((ul = pstg->AddRef()) <= 0)
  84. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  85. if ((ul = pstg->Release()) <= 0)
  86. error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
  87. #endif
  88. pstg->Unwrap();
  89. }
  90. void t_tmodify(void)
  91. {
  92. WStorage *pstgRoot, *pstgChild, *pstgChild2;
  93. WStream *pstm;
  94. // This test must use transacted mode to reproduce the
  95. // expected behavior
  96. ForceTransacted();
  97. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  98. 0, &pstgRoot);
  99. pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0,
  100. 0, &pstgChild);
  101. pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0,
  102. 0, &pstgChild2);
  103. pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  104. pstm->Unwrap();
  105. pstgChild2->Commit(0);
  106. VerifyStructure(pstgChild2->GetI(), "sStream");
  107. // Test renaming a closed stream
  108. pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
  109. VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
  110. // Test rename reversion
  111. pstgChild2->Revert();
  112. VerifyStructure(pstgChild2->GetI(), "sStream");
  113. // Test destruction of closed object
  114. pstgChild2->DestroyElement(STR("Stream"));
  115. pstgChild2->Commit(0);
  116. // Test create of previously deleted object
  117. pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  118. pstgChild2->Commit(0);
  119. VerifyStructure(pstgChild2->GetI(), "sStream");
  120. #if 0
  121. // 08/11/93 - Renaming open children no longer allowed
  122. // Test renaming an open stream
  123. pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
  124. VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
  125. #endif
  126. pstgChild2->Revert();
  127. VerifyStructure(pstgChild2->GetI(), "sStream");
  128. pstgChild2->DestroyElement(STR("Stream"));
  129. pstgChild2->Commit(0);
  130. pstm->Unwrap();
  131. pstgChild2->Unwrap();
  132. VerifyStructure(pstgChild->GetI(), "dChild2()");
  133. // Test rename of storage
  134. pstgChild->RenameElement(STR("Child2"), STR("RenamedChild"));
  135. pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0,
  136. &pstm);
  137. pstm->Unwrap();
  138. pstgChild->DestroyElement(STR("Stream"));
  139. pstgChild->Commit(0);
  140. // Test SetElementTimes
  141. FILETIME tm;
  142. STATSTG stat;
  143. tm.dwLowDateTime = 0x12345678;
  144. tm.dwHighDateTime = 0x9abcdef0;
  145. // Set when element not open
  146. pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL);
  147. pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL);
  148. pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm);
  149. pstgChild->OpenStorage(STR("RenamedChild"), NULL, STGP(WSTG_READWRITE),
  150. NULL, 0, &pstgChild2);
  151. pstgChild2->Stat(&stat, STATFLAG_NONAME);
  152. if (!IsEqualTime(stat.ctime, tm) ||
  153. !IsEqualTime(stat.mtime, tm))
  154. error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n");
  155. // Test SetClass and SetStateBits
  156. pstgChild2->SetClass(IID_IStorage);
  157. pstgChild2->SetStateBits(0xff00ff00, 0xffffffff);
  158. pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee);
  159. pstgChild2->Stat(&stat, STATFLAG_NONAME);
  160. if (!IsEqualCLSID(stat.clsid, IID_IStorage))
  161. error(EXIT_BADSC, "Class ID set to %s\n", GuidText(&stat.clsid));
  162. if (stat.grfStateBits != 0x11881188)
  163. error(EXIT_BADSC, "State bits set improperly: has %lX vs. %lX\n",
  164. stat.grfStateBits, 0x11881188);
  165. pstgChild2->Revert();
  166. pstgChild2->Stat(&stat, STATFLAG_NONAME);
  167. if (!IsEqualCLSID(stat.clsid, CLSID_NULL))
  168. error(EXIT_BADSC, "Class ID reverted to %s\n", GuidText(&stat.clsid));
  169. if (stat.grfStateBits != 0)
  170. error(EXIT_BADSC, "State bits reverted improperly: has %lX vs. %lX\n",
  171. stat.grfStateBits, 0);
  172. pstgChild2->Unwrap();
  173. pstgChild->Unwrap();
  174. VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
  175. pstgRoot->Revert();
  176. VerifyStructure(pstgRoot->GetI(), "");
  177. pstgRoot->Commit(0);
  178. VerifyStructure(pstgRoot->GetI(), "");
  179. pstgRoot->Unwrap();
  180. Unforce();
  181. }
  182. void t_dmodify(void)
  183. {
  184. WStorage *pstgRoot, *pstgChild, *pstgChild2;
  185. WStream *pstm;
  186. ULONG cbSize1, cbSize2;
  187. // This test must use direct mode to reproduce the
  188. // expected behavior
  189. ForceDirect();
  190. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  191. 0, &pstgRoot);
  192. pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0,
  193. 0, &pstgChild);
  194. pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0,
  195. 0, &pstgChild2);
  196. pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  197. pstm->Unwrap();
  198. VerifyStructure(pstgChild2->GetI(), "sStream");
  199. // Test renaming a closed stream
  200. pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
  201. VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
  202. // Test destroying a stream
  203. pstgChild2->DestroyElement(STR("RenamedStream"));
  204. #if 0
  205. // 08/11/93 - Renaming open child no longer allowed
  206. // Test renaming an open stream
  207. pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  208. VerifyStructure(pstgChild2->GetI(), "sStream");
  209. pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
  210. VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
  211. pstgChild2->DestroyElement(STR("RenamedStream"));
  212. pstm->Unwrap();
  213. #endif
  214. pstgChild2->Unwrap();
  215. VerifyStructure(pstgChild->GetI(), "dChild2()");
  216. // Test renaming a storage
  217. pstgChild->RenameElement(STR("Child2"), STR("RenamedChild"));
  218. pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0,
  219. &pstm);
  220. pstm->Unwrap();
  221. pstgChild->DestroyElement(STR("Stream"));
  222. // Test SetElementTimes
  223. FILETIME tm;
  224. STATSTG stat;
  225. tm.dwLowDateTime = 0x12345678;
  226. tm.dwHighDateTime = 0x9abcdef0;
  227. // Set when element not open
  228. pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL);
  229. pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL);
  230. pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm);
  231. pstgChild->OpenStorage(STR("RenamedChild"), NULL, STMP(WSTG_READWRITE),
  232. NULL, 0, &pstgChild2);
  233. pstgChild2->Stat(&stat, STATFLAG_NONAME);
  234. if (!IsEqualTime(stat.ctime, tm) ||
  235. !IsEqualTime(stat.mtime, tm))
  236. error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n");
  237. // Test SetClass and SetStateBits
  238. pstgChild2->SetClass(IID_IStorage);
  239. pstgChild2->SetStateBits(0xff00ff00, 0xffffffff);
  240. pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee);
  241. pstgChild2->Stat(&stat, STATFLAG_NONAME);
  242. if (!IsEqualCLSID(stat.clsid, IID_IStorage))
  243. error(EXIT_BADSC, "Class ID set improperly\n");
  244. if (stat.grfStateBits != 0x11881188)
  245. error(EXIT_BADSC, "State bits set improperly: has %lX vs. %lX\n",
  246. stat.grfStateBits, 0x11881188);
  247. pstgChild2->Unwrap();
  248. pstgChild->Unwrap();
  249. VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
  250. pstgRoot->Revert();
  251. VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
  252. pstgRoot->Commit(0);
  253. VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
  254. pstgRoot->DestroyElement(STR("Child"));
  255. VerifyStructure(pstgRoot->GetI(), "");
  256. // Verify that space is reclaimed after modifications
  257. pstgRoot->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  258. pstm->SetSize(65536);
  259. pstm->Unwrap();
  260. cbSize1 = Length(DRTDF);
  261. pstgRoot->DestroyElement(STR("Stream"));
  262. pstgRoot->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  263. pstm->SetSize(65536);
  264. pstm->Unwrap();
  265. cbSize2 = Length(DRTDF);
  266. if (cbSize1 != cbSize2)
  267. error(EXIT_BADSC, "Space is not being reclaimed, original %lu, "
  268. "now %lu\n", cbSize1, cbSize2);
  269. pstgRoot->Unwrap();
  270. WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  271. WSTG_DELETEONRELEASE, 0, &pstgRoot);
  272. // removal cases
  273. // 1) no right child
  274. CreateStructure(pstgRoot->GetI(), "d64,d32");
  275. VerifyStructure(pstgRoot->GetI(), "d64,d32");
  276. pstgRoot->DestroyElement(STR("64"));
  277. VerifyStructure(pstgRoot->GetI(), "d32");
  278. // 2) right child has no left child
  279. CreateStructure(pstgRoot->GetI(), "d64");
  280. VerifyStructure(pstgRoot->GetI(), "d32,d64");
  281. pstgRoot->DestroyElement(STR("32"));
  282. VerifyStructure(pstgRoot->GetI(), "d64");
  283. // 3) right child has left child
  284. CreateStructure(pstgRoot->GetI(), "d96,d80");
  285. VerifyStructure(pstgRoot->GetI(), "d64,d80,d96");
  286. pstgRoot->DestroyElement(STR("64"));
  287. VerifyStructure(pstgRoot->GetI(), "d80,d96");
  288. // 4) right child's left child has children
  289. CreateStructure(pstgRoot->GetI(), "d88,d84,d92");
  290. VerifyStructure(pstgRoot->GetI(), "d80,d84,d88,d92,d96");
  291. pstgRoot->DestroyElement(STR("80"));
  292. VerifyStructure(pstgRoot->GetI(), "d84,d88,d92,d96");
  293. pstgRoot->Unwrap();
  294. Unforce();
  295. }
  296. void t_stat(void)
  297. {
  298. WStorage *pstgRoot, *pstgChild;
  299. WStream *pstm;
  300. STATSTG stat;
  301. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  302. 0, &pstgRoot);
  303. pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, 0,
  304. &pstgChild);
  305. pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  306. pstm->Stat(&stat, 0);
  307. VerifyStat(&stat, STR("Stream"), STGTY_STREAM, STMP(WSTG_READWRITE));
  308. drtMemFree(stat.pwcsName);
  309. pstm->Stat(&stat, STATFLAG_NONAME);
  310. VerifyStat(&stat, NULL, STGTY_STREAM, STMP(WSTG_READWRITE));
  311. pstm->Unwrap();
  312. pstgChild->Stat(&stat, 0);
  313. VerifyStat(&stat, STR("Child"), STGTY_STORAGE, STGP(WSTG_READWRITE));
  314. drtMemFree(stat.pwcsName);
  315. pstgChild->Stat(&stat, STATFLAG_NONAME);
  316. VerifyStat(&stat, NULL, STGTY_STORAGE, STGP(WSTG_READWRITE));
  317. pstgChild->Unwrap();
  318. pstgRoot->Stat(&stat, 0);
  319. OLECHAR atcFullPath[_MAX_PATH];
  320. GetFullPath(DRTDF, atcFullPath);
  321. VerifyStat(&stat, atcFullPath, STGTY_STORAGE, ROOTP(WSTG_READWRITE));
  322. drtMemFree(stat.pwcsName);
  323. pstgRoot->Stat(&stat, STATFLAG_NONAME);
  324. VerifyStat(&stat, NULL, STGTY_STORAGE, ROOTP(WSTG_READWRITE));
  325. pstgRoot->Unwrap();
  326. }
  327. static char NUMBERS[] = "12345678901234567890123456789012345678901234567890";
  328. void t_stream(void)
  329. {
  330. WStorage *pstg;
  331. WStream *pstm, *pstmC;
  332. char buf[sizeof(NUMBERS)*2];
  333. ULONG cb, ulPos;
  334. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, 0, &pstg);
  335. pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  336. pstm->Write(NUMBERS, sizeof(NUMBERS), &cb);
  337. pstm->Commit(0);
  338. pstm->Seek(0, WSTM_SEEK_SET, &ulPos);
  339. if (ulPos != 0)
  340. error(EXIT_BADSC, "Incorrect seek, ptr is %lu\n", ulPos);
  341. pstm->Read(buf, sizeof(NUMBERS), &cb);
  342. if (strcmp(buf, NUMBERS))
  343. error(EXIT_BADSC, "Incorrect stream contents\n");
  344. pstm->SetSize(sizeof(NUMBERS)/2);
  345. pstm->Seek(0, WSTM_SEEK_SET, NULL);
  346. fExitOnFail = FALSE;
  347. pstm->Read(buf, sizeof(NUMBERS), &cb);
  348. fExitOnFail = TRUE;
  349. if (cb != sizeof(NUMBERS)/2)
  350. error(EXIT_BADSC, "SetSize failed to size stream properly\n");
  351. if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2))
  352. error(EXIT_BADSC, "SetSize corrupted contents\n");
  353. pstm->Clone(&pstmC);
  354. pstm->Seek(0, WSTM_SEEK_SET, NULL);
  355. pstm->CopyTo(pstmC, sizeof(NUMBERS)/2, NULL, NULL);
  356. pstm->Seek(0, WSTM_SEEK_SET, NULL);
  357. pstm->CopyTo(pstmC, sizeof(NUMBERS)&~1, NULL, NULL);
  358. pstm->Seek(0, WSTM_SEEK_SET, NULL);
  359. pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb);
  360. if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) ||
  361. memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) ||
  362. memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) ||
  363. memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2))
  364. error(EXIT_BADSC, "Stream contents incorrect\n");
  365. pstmC->Unwrap();
  366. pstm->Unwrap();
  367. pstg->Unwrap();
  368. }
  369. // Number of entries for enumeration test
  370. #define ENUMENTRIES 10
  371. // Flag indicating a name has already shown up in enumeration,
  372. // must not conflict with STGTY_*
  373. #define ENTRY_SEEN 0x100
  374. // Check the validity of an enumeration element
  375. static void elt_check(STATSTG *pstat, CStrList *psl)
  376. {
  377. SStrEntry *pse;
  378. pse = psl->Find(pstat->pwcsName);
  379. if (pse == NULL)
  380. error(EXIT_BADSC, "Spurious element '%s'\n", pstat->pwcsName);
  381. else if ((pse->user.dw & ~ENTRY_SEEN) != pstat->type)
  382. error(EXIT_BADSC, "Element '%s' has wrong type - "
  383. "has %lX vs. %lX\n", pstat->pwcsName, pstat->type,
  384. pse->user.dw & ~ENTRY_SEEN);
  385. else if (pse->user.dw & ENTRY_SEEN)
  386. error(EXIT_BADSC, "Element '%s' has already been seen\n",
  387. pstat->pwcsName);
  388. pse->user.dw |= ENTRY_SEEN;
  389. }
  390. // Do final validity checks for enumeration
  391. static void enum_list_check(CStrList *psl)
  392. {
  393. SStrEntry *pse;
  394. for (pse = psl->GetHead(); pse; pse = pse->pseNext)
  395. {
  396. if ((pse->user.dw & ENTRY_SEEN) == 0)
  397. error(EXIT_BADSC, "Element '%s' not found\n", pse->atc);
  398. pse->user.dw &= ~ENTRY_SEEN;
  399. }
  400. }
  401. void t_enum(void)
  402. {
  403. int i;
  404. OLECHAR atcName[CWCSTORAGENAME];
  405. WStorage *pstg, *pstg2;
  406. WStream *pstm;
  407. SStrEntry *pse;
  408. CStrList sl;
  409. // Create some entries to enumerate
  410. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, 0, &pstg);
  411. for (i = 0; i<ENUMENTRIES; i++)
  412. {
  413. olecsprintf(atcName, STR("Name%d"), rand());
  414. pse = sl.Add(atcName);
  415. if (rand()%100 < 50)
  416. {
  417. pse->user.dw = STGTY_STORAGE;
  418. pstg->CreateStorage(atcName, STGP(WSTG_READWRITE), 0, 0, &pstg2);
  419. pstg2->Unwrap();
  420. }
  421. else
  422. {
  423. pse->user.dw = STGTY_STREAM;
  424. pstg->CreateStream(atcName, STMP(WSTG_READWRITE), 0, 0, &pstm);
  425. pstm->Unwrap();
  426. }
  427. }
  428. WEnumSTATSTG *penm;
  429. STATSTG stat[2*ENUMENTRIES];
  430. SCODE sc;
  431. // Test plain, single element enumeration
  432. pstg->EnumElements(0, NULL, 0, &penm);
  433. for (;;)
  434. {
  435. sc = DfGetScode(penm->Next(1, stat, NULL));
  436. if (sc == S_FALSE)
  437. break;
  438. elt_check(stat, &sl);
  439. drtMemFree(stat->pwcsName);
  440. }
  441. enum_list_check(&sl);
  442. ULONG cFound;
  443. // Test rewind and multiple element enumeration with too many elements
  444. penm->Reset();
  445. sc = DfGetScode(penm->Next(ENUMENTRIES*2, stat, &cFound));
  446. if (sc != S_FALSE)
  447. error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of "
  448. "S_FALSE\n", ScText(sc), sc);
  449. if (cFound != ENUMENTRIES)
  450. error(EXIT_BADSC, "Enumerator found %lu entries instead of "
  451. "%d entries\n", cFound, ENUMENTRIES);
  452. for (; cFound > 0; cFound--)
  453. {
  454. elt_check(&stat[cFound-1], &sl);
  455. drtMemFree(stat[cFound-1].pwcsName);
  456. }
  457. enum_list_check(&sl);
  458. // Test skip and multiple enumeration with exact number of elements
  459. penm->Reset();
  460. penm->Skip(ENUMENTRIES/2);
  461. sc = DfGetScode(penm->Next(ENUMENTRIES-ENUMENTRIES/2, stat, &cFound));
  462. if (sc != S_OK)
  463. error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of "
  464. "S_OK\n", ScText(sc), sc);
  465. if (cFound != ENUMENTRIES-ENUMENTRIES/2)
  466. error(EXIT_BADSC, "Enumerator found %lu entries instead of "
  467. "%d entries\n", cFound, ENUMENTRIES-ENUMENTRIES/2);
  468. for (; cFound > 0; cFound--)
  469. {
  470. elt_check(&stat[cFound-1], &sl);
  471. drtMemFree(stat[cFound-1].pwcsName);
  472. }
  473. sc = DfGetScode(penm->Next(1, stat, NULL));
  474. if (sc != S_FALSE)
  475. error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of "
  476. "S_FALSE\n", ScText(sc), sc);
  477. penm->Unwrap();
  478. pstg->Unwrap();
  479. }
  480. #define SCT_CLASSID IID_ILockBytes
  481. #define SCT_STATEBITS 0xfef1f0f0
  482. void t_stgcopyto(void)
  483. {
  484. WStorage *pstgFrom, *pstgTo;
  485. STATSTG statFrom, statTo;
  486. WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  487. WSTG_DELETEONRELEASE, 0, &pstgFrom);
  488. pstgFrom->Stat(&statFrom, 0);
  489. // Set some interesting values to make sure they're copied
  490. pstgFrom->SetClass(SCT_CLASSID);
  491. pstgFrom->SetStateBits(SCT_STATEBITS, 0xffffffff);
  492. WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  493. WSTG_DELETEONRELEASE, 0, &pstgTo);
  494. CreateStructure(pstgFrom->GetI(), "dA(dB(dC(sA,sB,sC),sCs),sBs),sAs");
  495. CreateStructure(pstgTo->GetI(), "dA(dY(sZ),sBs)");
  496. pstgFrom->CopyTo(0, NULL, NULL, pstgTo);
  497. VerifyStructure(pstgTo->GetI(),
  498. "dA(dB(dC(sA,sB,sC),sCs),dY(sZ),sBs),sAs");
  499. pstgTo->Stat(&statTo, 0);
  500. if (!IsEqualCLSID(statTo.clsid, SCT_CLASSID))
  501. error(EXIT_BADSC, "Class ID mismatch after copy\n");
  502. if (statTo.grfStateBits != SCT_STATEBITS)
  503. error(EXIT_BADSC, "State bits mismatch: has %lX vs. %lX\n",
  504. statTo.grfStateBits, SCT_STATEBITS);
  505. pstgFrom->Unwrap();
  506. pstgTo->Unwrap();
  507. if (Exists(statFrom.pwcsName))
  508. error(EXIT_BADSC, "Storage '%s' not deleted\n", statFrom.pwcsName);
  509. drtMemFree(statFrom.pwcsName);
  510. if (Exists(statTo.pwcsName))
  511. error(EXIT_BADSC, "Storage '%s' not deleted\n", statTo.pwcsName);
  512. drtMemFree(statTo.pwcsName);
  513. }
  514. #define MARSHAL_STM STR("Marshal")
  515. static void do_marshal(WStorage *pstg, WStream *pstm)
  516. {
  517. WStorage *pstgMarshal;
  518. WStream *pstmMarshal;
  519. WStgCreateDocfile(MARSHALDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
  520. 0, &pstgMarshal);
  521. pstgMarshal->CreateStream(MARSHAL_STM, STMP(WSTG_READWRITE), 0, 0,
  522. &pstmMarshal);
  523. WCoMarshalInterface(pstmMarshal, IID_IStorage, pstg->GetI(), 0, NULL,
  524. MSHLFLAGS_NORMAL);
  525. WCoMarshalInterface(pstmMarshal, IID_IStream, pstm->GetI(), 0, NULL,
  526. MSHLFLAGS_NORMAL);
  527. pstmMarshal->Unwrap();
  528. pstgMarshal->Commit(0);
  529. pstgMarshal->Unwrap();
  530. }
  531. static char STREAM_DATA[] = "This is data to be written";
  532. static void do_unmarshal(WStorage **ppstg, WStream **ppstm)
  533. {
  534. IStorage *pistg;
  535. WStorage *pstgMarshal;
  536. WStream *pstmMarshal;
  537. IStream *pistm;
  538. WStgOpenStorage(MARSHALDF, NULL, ROOTP(WSTG_READWRITE), NULL, 0,
  539. &pstgMarshal);
  540. pstgMarshal->OpenStream(MARSHAL_STM, NULL, STMP(WSTG_READWRITE), 0,
  541. &pstmMarshal);
  542. WCoUnmarshalInterface(pstmMarshal, IID_IStorage, (void **)&pistg);
  543. *ppstg = WStorage::Wrap(pistg);
  544. WCoUnmarshalInterface(pstmMarshal, IID_IStream, (void **)&pistm);
  545. *ppstm = WStream::Wrap(pistm);
  546. pstmMarshal->Unwrap();
  547. pstgMarshal->Unwrap();
  548. }
  549. void t_marshal(void)
  550. {
  551. WStorage *pstg, *pstgM;
  552. WStream *pstm, *pstmM;
  553. ULONG cbRead, cbWritten;
  554. char buf[sizeof(STREAM_DATA)];
  555. WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  556. WSTG_DELETEONRELEASE, 0, &pstg);
  557. pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
  558. pstm->Write(STREAM_DATA, sizeof(STREAM_DATA), &cbWritten);
  559. CreateStructure(pstg->GetI(), "dChild(dChild(sStream))");
  560. do_marshal(pstg, pstm);
  561. do_unmarshal(&pstgM, &pstmM);
  562. pstm->Unwrap();
  563. pstg->Unwrap();
  564. pstmM->Seek(0, WSTM_SEEK_SET, NULL);
  565. pstmM->Read(buf, sizeof(STREAM_DATA), &cbRead);
  566. if (strcmp(buf, STREAM_DATA))
  567. error(EXIT_BADSC, "Stream data mismatch\n");
  568. pstmM->Unwrap();
  569. VerifyStructure(pstgM->GetI(), "dChild(dChild(sStream)),sStream");
  570. pstgM->Unwrap();
  571. }
  572. void t_stgmisc(void)
  573. {
  574. WStorage *pstg;
  575. SCODE sc;
  576. STATSTG stat;
  577. // Can't make this call in transacted mode because we want
  578. // the storage signature to make it into the file right away
  579. WStgCreateDocfile(DRTDF, WSTG_READWRITE | WSTG_CREATE |
  580. WSTG_SHARE_EXCLUSIVE, 0, &pstg);
  581. sc = DfGetScode(WStgIsStorageFile(DRTDF));
  582. if (sc == S_FALSE)
  583. error(EXIT_BADSC, "Open file - Should be a storage object\n");
  584. pstg->Unwrap();
  585. sc = DfGetScode(WStgIsStorageFile(DRTDF));
  586. if (sc == S_FALSE)
  587. error(EXIT_BADSC, "Closed file - Should be a storage object\n");
  588. WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  589. WSTG_DELETEONRELEASE, 0, &pstg);
  590. pstg->Stat(&stat, 0);
  591. if (!Exists(stat.pwcsName))
  592. error(EXIT_BADSC, "Storage '%s' not created\n", stat.pwcsName);
  593. pstg->Unwrap();
  594. if (Exists(stat.pwcsName))
  595. error(EXIT_BADSC, "Storage '%s' not deleted on release\n",
  596. stat.pwcsName);
  597. drtMemFree(stat.pwcsName);
  598. }
  599. void t_ilb(void)
  600. {
  601. WStorage *pstg;
  602. SCODE sc;
  603. // create an ILockBytes
  604. ILockBytes *pilb = new CMapBytes();
  605. if (pilb == NULL)
  606. error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
  607. // create a storage on the ILockBytes
  608. WStgCreateDocfileOnILockBytes(pilb,
  609. WSTG_READWRITE |
  610. WSTG_CREATE |
  611. WSTG_SHARE_EXCLUSIVE,
  612. 0, &pstg);
  613. // verify the ILockBytes
  614. sc = DfGetScode(WStgIsStorageILockBytes(pilb));
  615. if (sc == S_FALSE)
  616. error(EXIT_BADSC, "Open ILockBytes - Should be a storage object\n");
  617. // release the storage
  618. pstg->Unwrap();
  619. // verify the ILockBytes
  620. sc = DfGetScode(WStgIsStorageILockBytes(pilb));
  621. if (sc == S_FALSE)
  622. error(EXIT_BADSC, "Released ILockBytes - Should be a storage object\n");
  623. // open the ILockBytes
  624. WStgOpenStorageOnILockBytes(pilb, NULL, ROOTP(WSTG_READWRITE),
  625. NULL, 0, &pstg);
  626. // release the storage
  627. pstg->Unwrap();
  628. // release the ILockBytes
  629. pilb->Release();
  630. }
  631. void t_movecopy(void)
  632. {
  633. WStorage *pstgFrom, *pstgTo;
  634. STATSTG statFrom, statTo;
  635. // create a source
  636. WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  637. WSTG_DELETEONRELEASE, 0, &pstgFrom);
  638. pstgFrom->Stat(&statFrom, 0);
  639. // create a destination
  640. WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
  641. WSTG_DELETEONRELEASE, 0, &pstgTo);
  642. pstgTo->Stat(&statTo, 0);
  643. // populate source
  644. CreateStructure(pstgFrom->GetI(), "dA(dB(dC(sA,sB,sC),sCs),sBs),sAs");
  645. // move a storage
  646. pstgFrom->MoveElementTo(STR("A"), pstgTo, STR("M"), STGMOVE_MOVE);
  647. VerifyStructure(pstgFrom->GetI(),
  648. "sAs");
  649. VerifyStructure(pstgTo->GetI(),
  650. "dM(dB(dC(sA,sB,sC),sCs),sBs)");
  651. // copy a stream
  652. pstgFrom->MoveElementTo(STR("As"), pstgTo, STR("Bs"), STGMOVE_COPY);
  653. VerifyStructure(pstgFrom->GetI(),
  654. "sAs");
  655. VerifyStructure(pstgTo->GetI(),
  656. "dM(dB(dC(sA,sB,sC),sCs),sBs),sBs");
  657. pstgFrom->Unwrap();
  658. pstgTo->Unwrap();
  659. if (Exists(statFrom.pwcsName))
  660. error(EXIT_BADSC, "Storage '%s' not deleted\n", statFrom.pwcsName);
  661. drtMemFree(statFrom.pwcsName);
  662. if (Exists(statTo.pwcsName))
  663. error(EXIT_BADSC, "Storage '%s' not deleted\n", statTo.pwcsName);
  664. drtMemFree(statTo.pwcsName);
  665. }