PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 2ms

/wine-1.5.9/dlls/msi/tests/db.c

#
C | 9704 lines | 9317 code | 307 blank | 80 comment | 358 complexity | 3f02e5e703b9a8c20cea89b6dc369415 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0
  1. /*
  2. * Copyright (C) 2005 Mike McCormack for CodeWeavers
  3. *
  4. * A test program for MSI database files.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #define COBJMACROS
  21. #include <stdio.h>
  22. #include <windows.h>
  23. #include <msi.h>
  24. #include <msidefs.h>
  25. #include <msiquery.h>
  26. #include <objidl.h>
  27. #include "wine/test.h"
  28. static const char *msifile = "winetest-db.msi";
  29. static const char *msifile2 = "winetst2-db.msi";
  30. static const char *mstfile = "winetst-db.mst";
  31. static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','-','d','b','.','m','s','i',0};
  32. static void test_msidatabase(void)
  33. {
  34. MSIHANDLE hdb = 0, hdb2 = 0;
  35. UINT res;
  36. DeleteFile(msifile);
  37. res = MsiOpenDatabase( msifile, msifile2, &hdb );
  38. ok( res == ERROR_OPEN_FAILED, "expected failure\n");
  39. res = MsiOpenDatabase( msifile, (LPSTR) 0xff, &hdb );
  40. ok( res == ERROR_INVALID_PARAMETER, "expected failure\n");
  41. res = MsiCloseHandle( hdb );
  42. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  43. /* create an empty database */
  44. res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
  45. ok( res == ERROR_SUCCESS , "Failed to create database\n" );
  46. res = MsiDatabaseCommit( hdb );
  47. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  48. ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
  49. res = MsiCloseHandle( hdb );
  50. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  51. res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
  52. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  53. ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile2 ), "database should exist\n");
  54. res = MsiDatabaseCommit( hdb2 );
  55. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  56. res = MsiCloseHandle( hdb2 );
  57. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  58. res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
  59. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  60. res = MsiCloseHandle( hdb2 );
  61. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  62. ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile2 ), "uncommitted database should not exist\n");
  63. res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
  64. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  65. res = MsiDatabaseCommit( hdb2 );
  66. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  67. res = MsiCloseHandle( hdb2 );
  68. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  69. ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile2 ), "committed database should exist\n");
  70. res = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
  71. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  72. res = MsiDatabaseCommit( hdb );
  73. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  74. res = MsiCloseHandle( hdb );
  75. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  76. res = MsiOpenDatabase( msifile, MSIDBOPEN_DIRECT, &hdb );
  77. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  78. res = MsiCloseHandle( hdb );
  79. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  80. res = MsiOpenDatabase( msifile, MSIDBOPEN_TRANSACT, &hdb );
  81. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  82. res = MsiCloseHandle( hdb );
  83. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  84. ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
  85. /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
  86. res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
  87. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  88. ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
  89. res = MsiCloseHandle( hdb );
  90. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  91. ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile ), "database should exist\n");
  92. res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
  93. ok( res == ERROR_SUCCESS , "Failed to open database\n" );
  94. res = MsiDatabaseCommit( hdb );
  95. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  96. ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
  97. res = MsiCloseHandle( hdb );
  98. ok( res == ERROR_SUCCESS , "Failed to close database\n" );
  99. res = DeleteFile( msifile2 );
  100. ok( res == TRUE, "Failed to delete database\n" );
  101. res = DeleteFile( msifile );
  102. ok( res == TRUE, "Failed to delete database\n" );
  103. }
  104. static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
  105. {
  106. MSIHANDLE hview = 0;
  107. UINT r, ret;
  108. if (phrec)
  109. *phrec = 0;
  110. /* open a select query */
  111. r = MsiDatabaseOpenView(hdb, query, &hview);
  112. if (r != ERROR_SUCCESS)
  113. return r;
  114. r = MsiViewExecute(hview, 0);
  115. if (r != ERROR_SUCCESS)
  116. return r;
  117. ret = MsiViewFetch(hview, phrec);
  118. r = MsiViewClose(hview);
  119. if (r != ERROR_SUCCESS)
  120. return r;
  121. r = MsiCloseHandle(hview);
  122. if (r != ERROR_SUCCESS)
  123. return r;
  124. return ret;
  125. }
  126. static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
  127. {
  128. MSIHANDLE hview = 0;
  129. UINT r;
  130. r = MsiDatabaseOpenView(hdb, query, &hview);
  131. if( r != ERROR_SUCCESS )
  132. return r;
  133. r = MsiViewExecute(hview, hrec);
  134. if( r == ERROR_SUCCESS )
  135. r = MsiViewClose(hview);
  136. MsiCloseHandle(hview);
  137. return r;
  138. }
  139. static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
  140. {
  141. MSIHANDLE hview = 0;
  142. UINT r;
  143. r = MsiDatabaseOpenViewW(hdb, query, &hview);
  144. if( r != ERROR_SUCCESS )
  145. return r;
  146. r = MsiViewExecute(hview, hrec);
  147. if( r == ERROR_SUCCESS )
  148. r = MsiViewClose(hview);
  149. MsiCloseHandle(hview);
  150. return r;
  151. }
  152. static UINT create_component_table( MSIHANDLE hdb )
  153. {
  154. return run_query( hdb, 0,
  155. "CREATE TABLE `Component` ( "
  156. "`Component` CHAR(72) NOT NULL, "
  157. "`ComponentId` CHAR(38), "
  158. "`Directory_` CHAR(72) NOT NULL, "
  159. "`Attributes` SHORT NOT NULL, "
  160. "`Condition` CHAR(255), "
  161. "`KeyPath` CHAR(72) "
  162. "PRIMARY KEY `Component`)" );
  163. }
  164. static UINT create_custom_action_table( MSIHANDLE hdb )
  165. {
  166. return run_query( hdb, 0,
  167. "CREATE TABLE `CustomAction` ( "
  168. "`Action` CHAR(72) NOT NULL, "
  169. "`Type` SHORT NOT NULL, "
  170. "`Source` CHAR(72), "
  171. "`Target` CHAR(255) "
  172. "PRIMARY KEY `Action`)" );
  173. }
  174. static UINT create_directory_table( MSIHANDLE hdb )
  175. {
  176. return run_query( hdb, 0,
  177. "CREATE TABLE `Directory` ( "
  178. "`Directory` CHAR(255) NOT NULL, "
  179. "`Directory_Parent` CHAR(255), "
  180. "`DefaultDir` CHAR(255) NOT NULL "
  181. "PRIMARY KEY `Directory`)" );
  182. }
  183. static UINT create_feature_components_table( MSIHANDLE hdb )
  184. {
  185. return run_query( hdb, 0,
  186. "CREATE TABLE `FeatureComponents` ( "
  187. "`Feature_` CHAR(38) NOT NULL, "
  188. "`Component_` CHAR(72) NOT NULL "
  189. "PRIMARY KEY `Feature_`, `Component_` )" );
  190. }
  191. static UINT create_std_dlls_table( MSIHANDLE hdb )
  192. {
  193. return run_query( hdb, 0,
  194. "CREATE TABLE `StdDlls` ( "
  195. "`File` CHAR(255) NOT NULL, "
  196. "`Binary_` CHAR(72) NOT NULL "
  197. "PRIMARY KEY `File` )" );
  198. }
  199. static UINT create_binary_table( MSIHANDLE hdb )
  200. {
  201. return run_query( hdb, 0,
  202. "CREATE TABLE `Binary` ( "
  203. "`Name` CHAR(72) NOT NULL, "
  204. "`Data` CHAR(72) NOT NULL "
  205. "PRIMARY KEY `Name` )" );
  206. }
  207. #define make_add_entry(type, qtext) \
  208. static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
  209. { \
  210. char insert[] = qtext; \
  211. char *query; \
  212. UINT sz, r; \
  213. sz = strlen(values) + sizeof insert; \
  214. query = HeapAlloc(GetProcessHeap(),0,sz); \
  215. sprintf(query,insert,values); \
  216. r = run_query( hdb, 0, query ); \
  217. HeapFree(GetProcessHeap(), 0, query); \
  218. return r; \
  219. }
  220. make_add_entry(component,
  221. "INSERT INTO `Component` "
  222. "(`Component`, `ComponentId`, `Directory_`, "
  223. "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
  224. make_add_entry(custom_action,
  225. "INSERT INTO `CustomAction` "
  226. "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
  227. make_add_entry(feature_components,
  228. "INSERT INTO `FeatureComponents` "
  229. "(`Feature_`, `Component_`) VALUES( %s )")
  230. make_add_entry(std_dlls,
  231. "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
  232. make_add_entry(binary,
  233. "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
  234. static void test_msiinsert(void)
  235. {
  236. MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0;
  237. UINT r;
  238. const char *query;
  239. char buf[80];
  240. DWORD sz;
  241. DeleteFile(msifile);
  242. /* just MsiOpenDatabase should not create a file */
  243. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  244. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  245. /* create a table */
  246. query = "CREATE TABLE `phone` ( "
  247. "`id` INT, `name` CHAR(32), `number` CHAR(32) "
  248. "PRIMARY KEY `id`)";
  249. r = MsiDatabaseOpenView(hdb, query, &hview);
  250. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  251. r = MsiViewExecute(hview, 0);
  252. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  253. r = MsiViewClose(hview);
  254. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  255. r = MsiCloseHandle(hview);
  256. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  257. query = "SELECT * FROM phone WHERE number = '8675309'";
  258. r = MsiDatabaseOpenView(hdb, query, &hview2);
  259. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  260. r = MsiViewExecute(hview2, 0);
  261. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  262. r = MsiViewFetch(hview2, &hrec);
  263. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
  264. /* insert a value into it */
  265. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  266. "VALUES('1', 'Abe', '8675309')";
  267. r = MsiDatabaseOpenView(hdb, query, &hview);
  268. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  269. r = MsiViewExecute(hview, 0);
  270. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  271. r = MsiViewClose(hview);
  272. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  273. r = MsiCloseHandle(hview);
  274. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  275. r = MsiViewFetch(hview2, &hrec);
  276. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
  277. r = MsiViewExecute(hview2, 0);
  278. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  279. r = MsiViewFetch(hview2, &hrec);
  280. ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r);
  281. r = MsiCloseHandle(hrec);
  282. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  283. r = MsiViewClose(hview2);
  284. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  285. r = MsiCloseHandle(hview2);
  286. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  287. query = "SELECT * FROM `phone` WHERE `id` = 1";
  288. r = do_query(hdb, query, &hrec);
  289. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  290. /* check the record contains what we put in it */
  291. r = MsiRecordGetFieldCount(hrec);
  292. ok(r == 3, "record count wrong\n");
  293. r = MsiRecordIsNull(hrec, 0);
  294. ok(r == FALSE, "field 0 not null\n");
  295. r = MsiRecordGetInteger(hrec, 1);
  296. ok(r == 1, "field 1 contents wrong\n");
  297. sz = sizeof buf;
  298. r = MsiRecordGetString(hrec, 2, buf, &sz);
  299. ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
  300. ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
  301. sz = sizeof buf;
  302. r = MsiRecordGetString(hrec, 3, buf, &sz);
  303. ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
  304. ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
  305. r = MsiCloseHandle(hrec);
  306. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  307. /* open a select query */
  308. hrec = 100;
  309. query = "SELECT * FROM `phone` WHERE `id` >= 10";
  310. r = do_query(hdb, query, &hrec);
  311. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
  312. ok(hrec == 0, "hrec should be null\n");
  313. r = MsiCloseHandle(hrec);
  314. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  315. query = "SELECT * FROM `phone` WHERE `id` < 0";
  316. r = do_query(hdb, query, &hrec);
  317. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
  318. query = "SELECT * FROM `phone` WHERE `id` <= 0";
  319. r = do_query(hdb, query, &hrec);
  320. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
  321. query = "SELECT * FROM `phone` WHERE `id` <> 1";
  322. r = do_query(hdb, query, &hrec);
  323. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
  324. query = "SELECT * FROM `phone` WHERE `id` > 10";
  325. r = do_query(hdb, query, &hrec);
  326. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
  327. /* now try a few bad INSERT xqueries */
  328. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  329. "VALUES(?, ?)";
  330. r = MsiDatabaseOpenView(hdb, query, &hview);
  331. ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
  332. /* construct a record to insert */
  333. hrec = MsiCreateRecord(4);
  334. r = MsiRecordSetInteger(hrec, 1, 2);
  335. ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
  336. r = MsiRecordSetString(hrec, 2, "Adam");
  337. ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
  338. r = MsiRecordSetString(hrec, 3, "96905305");
  339. ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
  340. /* insert another value, using a record and wildcards */
  341. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  342. "VALUES(?, ?, ?)";
  343. r = MsiDatabaseOpenView(hdb, query, &hview);
  344. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  345. if (r == ERROR_SUCCESS)
  346. {
  347. r = MsiViewExecute(hview, hrec);
  348. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  349. r = MsiViewClose(hview);
  350. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  351. r = MsiCloseHandle(hview);
  352. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  353. }
  354. r = MsiCloseHandle(hrec);
  355. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  356. r = MsiViewFetch(0, NULL);
  357. ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
  358. r = MsiDatabaseCommit(hdb);
  359. ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
  360. r = MsiCloseHandle(hdb);
  361. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  362. r = DeleteFile(msifile);
  363. ok(r == TRUE, "file didn't exist after commit\n");
  364. }
  365. static void test_msidecomposedesc(void)
  366. {
  367. UINT (WINAPI *pMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
  368. char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
  369. const char *desc;
  370. UINT r;
  371. DWORD len;
  372. HMODULE hmod;
  373. hmod = GetModuleHandle("msi.dll");
  374. pMsiDecomposeDescriptorA = (void*)GetProcAddress(hmod, "MsiDecomposeDescriptorA");
  375. if (!pMsiDecomposeDescriptorA)
  376. return;
  377. /* test a valid feature descriptor */
  378. desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
  379. len = 0;
  380. r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
  381. ok(r == ERROR_SUCCESS, "returned an error\n");
  382. ok(len == strlen(desc), "length was wrong\n");
  383. ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
  384. ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
  385. ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
  386. /* test an invalid feature descriptor with too many characters */
  387. desc = "']gAVn-}f(ZXfeAR6.ji"
  388. "ThisWillFailIfTheresMoreThanAGuidsChars>"
  389. "3w2x^IGfe?CxI5heAvk.";
  390. len = 0;
  391. r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
  392. ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
  393. /*
  394. * Test a valid feature descriptor with the
  395. * maximum number of characters and some trailing characters.
  396. */
  397. desc = "']gAVn-}f(ZXfeAR6.ji"
  398. "ThisWillWorkIfTheresLTEThanAGuidsChars>"
  399. "3w2x^IGfe?CxI5heAvk."
  400. "extra";
  401. len = 0;
  402. r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
  403. ok(r == ERROR_SUCCESS, "returned wrong error\n");
  404. ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
  405. len = 0;
  406. r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
  407. ok(r == ERROR_SUCCESS, "returned wrong error\n");
  408. ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
  409. len = 0;
  410. r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
  411. ok(r == ERROR_SUCCESS, "returned wrong error\n");
  412. ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
  413. len = 0;
  414. r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
  415. ok(r == ERROR_SUCCESS, "returned wrong error\n");
  416. ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
  417. len = 0;
  418. r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
  419. ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
  420. ok(len == 0, "length wrong\n");
  421. r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL);
  422. ok(r == ERROR_SUCCESS, "returned wrong error\n");
  423. }
  424. static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
  425. {
  426. MSIHANDLE htab = 0;
  427. UINT res;
  428. res = MsiDatabaseOpenView( hdb, szQuery, &htab );
  429. if(res == ERROR_SUCCESS )
  430. {
  431. UINT r;
  432. r = MsiViewExecute( htab, hrec );
  433. if(r != ERROR_SUCCESS )
  434. res = r;
  435. r = MsiViewClose( htab );
  436. if(r != ERROR_SUCCESS )
  437. res = r;
  438. r = MsiCloseHandle( htab );
  439. if(r != ERROR_SUCCESS )
  440. res = r;
  441. }
  442. return res;
  443. }
  444. static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
  445. {
  446. return try_query_param( hdb, szQuery, 0 );
  447. }
  448. static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
  449. {
  450. MSIHANDLE hrec = 0;
  451. UINT r;
  452. hrec = MsiCreateRecord( 1 );
  453. MsiRecordSetString( hrec, 1, "Hello");
  454. r = try_query_param( hdb, szQuery, hrec );
  455. MsiCloseHandle( hrec );
  456. return r;
  457. }
  458. static void test_msibadqueries(void)
  459. {
  460. MSIHANDLE hdb = 0;
  461. UINT r;
  462. DeleteFile(msifile);
  463. /* just MsiOpenDatabase should not create a file */
  464. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  465. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  466. r = MsiDatabaseCommit( hdb );
  467. ok(r == ERROR_SUCCESS , "Failed to commit database\n");
  468. r = MsiCloseHandle( hdb );
  469. ok(r == ERROR_SUCCESS , "Failed to close database\n");
  470. /* open it readonly */
  471. r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb );
  472. ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
  473. /* add a table to it */
  474. r = try_query( hdb, "select * from _Tables");
  475. ok(r == ERROR_SUCCESS , "query 1 failed\n");
  476. r = MsiCloseHandle( hdb );
  477. ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
  478. /* open it read/write */
  479. r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
  480. ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
  481. /* a bunch of test queries that fail with the native MSI */
  482. r = try_query( hdb, "CREATE TABLE");
  483. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
  484. r = try_query( hdb, "CREATE TABLE `a`");
  485. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
  486. r = try_query( hdb, "CREATE TABLE `a` ()");
  487. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
  488. r = try_query( hdb, "CREATE TABLE `a` (`b`)");
  489. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
  490. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
  491. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
  492. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
  493. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
  494. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
  495. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
  496. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
  497. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
  498. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
  499. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
  500. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
  501. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
  502. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
  503. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
  504. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
  505. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
  506. r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
  507. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
  508. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
  509. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
  510. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
  511. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
  512. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
  513. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
  514. r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
  515. ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
  516. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
  517. ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
  518. r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
  519. ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
  520. r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
  521. "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
  522. ok(r == ERROR_SUCCESS , "query 4 failed\n");
  523. r = MsiDatabaseCommit( hdb );
  524. ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
  525. r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
  526. "PRIMARY KEY `foo`)");
  527. ok(r == ERROR_SUCCESS , "query 4 failed\n");
  528. r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )");
  529. ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
  530. r = MsiDatabaseCommit( hdb );
  531. ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
  532. r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
  533. "PRIMARY KEY `ba`)");
  534. ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
  535. r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
  536. ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
  537. r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
  538. "PRIMARY KEY `t`)");
  539. ok(r == ERROR_SUCCESS , "query 7 failed\n");
  540. r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
  541. ok(r == ERROR_SUCCESS , "query 8 failed\n");
  542. r = try_query( hdb, "select * from c");
  543. ok(r == ERROR_SUCCESS , "query failed\n");
  544. r = try_query( hdb, "select * from c where b = 'x");
  545. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  546. r = try_query( hdb, "select * from c where b = 'x'");
  547. ok(r == ERROR_SUCCESS, "query failed\n");
  548. r = try_query( hdb, "select * from 'c'");
  549. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  550. r = try_query( hdb, "select * from ''");
  551. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  552. r = try_query( hdb, "select * from c where b = x");
  553. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  554. r = try_query( hdb, "select * from c where b = \"x\"");
  555. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  556. r = try_query( hdb, "select * from c where b = 'x'");
  557. ok(r == ERROR_SUCCESS, "query failed\n");
  558. r = try_query( hdb, "select * from c where b = '\"x'");
  559. ok(r == ERROR_SUCCESS, "query failed\n");
  560. if (0) /* FIXME: this query causes trouble with other tests */
  561. {
  562. r = try_query( hdb, "select * from c where b = '\\\'x'");
  563. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  564. }
  565. r = try_query( hdb, "select * from 'c'");
  566. ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
  567. r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`");
  568. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  569. r = try_query( hdb, "select `c`.b` from `c`");
  570. ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  571. r = try_query( hdb, "select `c`.`b from `c`");
  572. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  573. r = try_query( hdb, "select `c`.b from `c`");
  574. ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  575. r = try_query( hdb, "select `c.`b` from `c`");
  576. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  577. r = try_query( hdb, "select c`.`b` from `c`");
  578. ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  579. r = try_query( hdb, "select c.`b` from `c`");
  580. ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  581. r = try_query( hdb, "select `c`.`b` from c`");
  582. ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  583. r = try_query( hdb, "select `c`.`b` from `c");
  584. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  585. r = try_query( hdb, "select `c`.`b` from c");
  586. ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  587. r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
  588. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  589. r = try_query( hdb, "SELECT * FROM \5a" );
  590. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  591. r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
  592. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  593. r = try_query( hdb, "SELECT * FROM a\5" );
  594. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  595. r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
  596. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  597. r = try_query( hdb, "SELECT * FROM -a" );
  598. todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  599. r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
  600. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  601. r = try_query( hdb, "SELECT * FROM a-" );
  602. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  603. r = MsiCloseHandle( hdb );
  604. ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
  605. r = DeleteFile( msifile );
  606. ok(r == TRUE, "file didn't exist after commit\n");
  607. }
  608. static void test_viewmodify(void)
  609. {
  610. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  611. UINT r;
  612. MSIDBERROR err;
  613. const char *query;
  614. char buffer[0x100];
  615. DWORD sz;
  616. DeleteFile(msifile);
  617. /* just MsiOpenDatabase should not create a file */
  618. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  619. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  620. query = "CREATE TABLE `phone` ( "
  621. "`id` INT, `name` CHAR(32), `number` CHAR(32) "
  622. "PRIMARY KEY `id`)";
  623. r = run_query( hdb, 0, query );
  624. ok(r == ERROR_SUCCESS, "query failed\n");
  625. query = "CREATE TABLE `_Validation` ( "
  626. "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
  627. "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
  628. "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
  629. "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)";
  630. r = run_query( hdb, 0, query );
  631. ok(r == ERROR_SUCCESS, "query failed\n");
  632. query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) "
  633. "VALUES('phone', 'id', 'N')";
  634. r = run_query( hdb, 0, query );
  635. ok(r == ERROR_SUCCESS, "query failed\n");
  636. /* check what the error function reports without doing anything */
  637. sz = 0;
  638. /* passing NULL as the 3rd param make function to crash on older platforms */
  639. err = MsiViewGetError( 0, NULL, &sz );
  640. ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
  641. /* open a view */
  642. query = "SELECT * FROM `phone`";
  643. r = MsiDatabaseOpenView(hdb, query, &hview);
  644. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  645. /* see what happens with a good hview and bad args */
  646. err = MsiViewGetError( hview, NULL, NULL );
  647. ok(err == MSIDBERROR_INVALIDARG || err == MSIDBERROR_NOERROR,
  648. "MsiViewGetError returns %u (expected -3)\n", err);
  649. err = MsiViewGetError( hview, buffer, NULL );
  650. ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
  651. /* see what happens with a zero length buffer */
  652. sz = 0;
  653. buffer[0] = 'x';
  654. err = MsiViewGetError( hview, buffer, &sz );
  655. ok(err == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
  656. ok(buffer[0] == 'x', "buffer cleared\n");
  657. ok(sz == 0, "size not zero\n");
  658. /* ok this one is strange */
  659. sz = 0;
  660. err = MsiViewGetError( hview, NULL, &sz );
  661. ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
  662. ok(sz == 0, "size not zero\n");
  663. /* see if it really has an error */
  664. sz = sizeof buffer;
  665. buffer[0] = 'x';
  666. err = MsiViewGetError( hview, buffer, &sz );
  667. ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
  668. ok(buffer[0] == 0, "buffer not cleared\n");
  669. ok(sz == 0, "size not zero\n");
  670. r = MsiViewExecute(hview, 0);
  671. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  672. /* try some invalid records */
  673. r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
  674. ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
  675. r = MsiViewModify(hview, -1, 0 );
  676. ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
  677. /* try an small record */
  678. hrec = MsiCreateRecord(1);
  679. r = MsiViewModify(hview, -1, hrec );
  680. ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
  681. sz = sizeof buffer;
  682. buffer[0] = 'x';
  683. err = MsiViewGetError( hview, buffer, &sz );
  684. ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
  685. ok(buffer[0] == 0, "buffer not cleared\n");
  686. ok(sz == 0, "size not zero\n");
  687. r = MsiCloseHandle(hrec);
  688. ok(r == ERROR_SUCCESS, "failed to close record\n");
  689. /* insert a valid record */
  690. hrec = MsiCreateRecord(3);
  691. r = MsiRecordSetInteger(hrec, 1, 1);
  692. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  693. r = MsiRecordSetString(hrec, 2, "bob");
  694. ok(r == ERROR_SUCCESS, "failed to set string\n");
  695. r = MsiRecordSetString(hrec, 3, "7654321");
  696. ok(r == ERROR_SUCCESS, "failed to set string\n");
  697. r = MsiViewExecute(hview, 0);
  698. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  699. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
  700. ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
  701. /* validate it */
  702. r = MsiViewExecute(hview, 0);
  703. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  704. r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec );
  705. ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r);
  706. sz = sizeof buffer;
  707. buffer[0] = 'x';
  708. err = MsiViewGetError( hview, buffer, &sz );
  709. ok(err == MSIDBERROR_DUPLICATEKEY, "MsiViewGetError returned %u\n", err);
  710. ok(!strcmp(buffer, "id"), "expected \"id\" c, got \"%s\"\n", buffer);
  711. ok(sz == 2, "size not 2\n");
  712. /* insert the same thing again */
  713. r = MsiViewExecute(hview, 0);
  714. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  715. /* should fail ... */
  716. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
  717. ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
  718. /* try to merge the same record */
  719. r = MsiViewExecute(hview, 0);
  720. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  721. r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
  722. ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
  723. r = MsiCloseHandle(hrec);
  724. ok(r == ERROR_SUCCESS, "failed to close record\n");
  725. /* try merging a new record */
  726. hrec = MsiCreateRecord(3);
  727. r = MsiRecordSetInteger(hrec, 1, 10);
  728. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  729. r = MsiRecordSetString(hrec, 2, "pepe");
  730. ok(r == ERROR_SUCCESS, "failed to set string\n");
  731. r = MsiRecordSetString(hrec, 3, "7654321");
  732. ok(r == ERROR_SUCCESS, "failed to set string\n");
  733. r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
  734. ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
  735. r = MsiViewExecute(hview, 0);
  736. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  737. r = MsiCloseHandle(hrec);
  738. ok(r == ERROR_SUCCESS, "failed to close record\n");
  739. r = MsiViewClose(hview);
  740. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  741. r = MsiCloseHandle(hview);
  742. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  743. query = "SELECT * FROM `phone`";
  744. r = MsiDatabaseOpenView(hdb, query, &hview);
  745. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  746. r = MsiViewExecute(hview, 0);
  747. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  748. r = MsiViewFetch(hview, &hrec);
  749. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  750. r = MsiRecordGetInteger(hrec, 1);
  751. ok(r == 1, "Expected 1, got %d\n", r);
  752. sz = sizeof(buffer);
  753. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  754. ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
  755. ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
  756. sz = sizeof(buffer);
  757. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  758. ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
  759. ok(!lstrcmp(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
  760. /* update the view, non-primary key */
  761. r = MsiRecordSetString(hrec, 3, "3141592");
  762. ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
  763. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  764. ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
  765. /* do it again */
  766. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  767. ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
  768. /* update the view, primary key */
  769. r = MsiRecordSetInteger(hrec, 1, 5);
  770. ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
  771. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  772. ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
  773. r = MsiCloseHandle(hrec);
  774. ok(r == ERROR_SUCCESS, "failed to close record\n");
  775. r = MsiViewClose(hview);
  776. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  777. r = MsiCloseHandle(hview);
  778. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  779. query = "SELECT * FROM `phone`";
  780. r = MsiDatabaseOpenView(hdb, query, &hview);
  781. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  782. r = MsiViewExecute(hview, 0);
  783. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  784. r = MsiViewFetch(hview, &hrec);
  785. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  786. r = MsiRecordGetInteger(hrec, 1);
  787. ok(r == 1, "Expected 1, got %d\n", r);
  788. sz = sizeof(buffer);
  789. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  790. ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
  791. ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
  792. sz = sizeof(buffer);
  793. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  794. ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
  795. ok(!lstrcmp(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
  796. r = MsiCloseHandle(hrec);
  797. ok(r == ERROR_SUCCESS, "failed to close record\n");
  798. /* use a record that doesn't come from a view fetch */
  799. hrec = MsiCreateRecord(3);
  800. ok(hrec != 0, "MsiCreateRecord failed\n");
  801. r = MsiRecordSetInteger(hrec, 1, 3);
  802. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  803. r = MsiRecordSetString(hrec, 2, "jane");
  804. ok(r == ERROR_SUCCESS, "failed to set string\n");
  805. r = MsiRecordSetString(hrec, 3, "112358");
  806. ok(r == ERROR_SUCCESS, "failed to set string\n");
  807. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  808. ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  809. r = MsiCloseHandle(hrec);
  810. ok(r == ERROR_SUCCESS, "failed to close record\n");
  811. /* use a record that doesn't come from a view fetch, primary key matches */
  812. hrec = MsiCreateRecord(3);
  813. ok(hrec != 0, "MsiCreateRecord failed\n");
  814. r = MsiRecordSetInteger(hrec, 1, 1);
  815. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  816. r = MsiRecordSetString(hrec, 2, "jane");
  817. ok(r == ERROR_SUCCESS, "failed to set string\n");
  818. r = MsiRecordSetString(hrec, 3, "112358");
  819. ok(r == ERROR_SUCCESS, "failed to set string\n");
  820. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  821. ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
  822. r = MsiCloseHandle(hrec);
  823. ok(r == ERROR_SUCCESS, "failed to close record\n");
  824. hrec = MsiCreateRecord(3);
  825. r = MsiRecordSetInteger(hrec, 1, 2);
  826. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  827. r = MsiRecordSetString(hrec, 2, "nick");
  828. ok(r == ERROR_SUCCESS, "failed to set string\n");
  829. r = MsiRecordSetString(hrec, 3, "141421");
  830. ok(r == ERROR_SUCCESS, "failed to set string\n");
  831. r = MsiViewExecute(hview, 0);
  832. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  833. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
  834. ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
  835. r = MsiCloseHandle(hrec);
  836. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  837. r = MsiViewClose(hview);
  838. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  839. r = MsiCloseHandle(hview);
  840. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  841. query = "SELECT * FROM `phone` WHERE `id` = 1";
  842. r = MsiDatabaseOpenView(hdb, query, &hview);
  843. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  844. r = MsiViewExecute(hview, 0);
  845. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  846. r = MsiViewFetch(hview, &hrec);
  847. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  848. /* change the id to match the second row */
  849. r = MsiRecordSetInteger(hrec, 1, 2);
  850. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  851. r = MsiRecordSetString(hrec, 2, "jerry");
  852. ok(r == ERROR_SUCCESS, "failed to set string\n");
  853. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  854. ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
  855. r = MsiCloseHandle(hrec);
  856. ok(r == ERROR_SUCCESS, "failed to close record\n");
  857. r = MsiViewClose(hview);
  858. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  859. r = MsiCloseHandle(hview);
  860. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  861. /* broader search */
  862. query = "SELECT * FROM `phone` ORDER BY `id`";
  863. r = MsiDatabaseOpenView(hdb, query, &hview);
  864. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  865. r = MsiViewExecute(hview, 0);
  866. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  867. r = MsiViewFetch(hview, &hrec);
  868. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  869. /* change the id to match the second row */
  870. r = MsiRecordSetInteger(hrec, 1, 2);
  871. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  872. r = MsiRecordSetString(hrec, 2, "jerry");
  873. ok(r == ERROR_SUCCESS, "failed to set string\n");
  874. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  875. ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
  876. r = MsiCloseHandle(hrec);
  877. ok(r == ERROR_SUCCESS, "failed to close record\n");
  878. r = MsiViewClose(hview);
  879. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  880. r = MsiCloseHandle(hview);
  881. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  882. r = MsiCloseHandle( hdb );
  883. ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
  884. }
  885. static MSIHANDLE create_db(void)
  886. {
  887. MSIHANDLE hdb = 0;
  888. UINT res;
  889. DeleteFile(msifile);
  890. /* create an empty database */
  891. res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
  892. ok( res == ERROR_SUCCESS , "Failed to create database\n" );
  893. if( res != ERROR_SUCCESS )
  894. return hdb;
  895. res = MsiDatabaseCommit( hdb );
  896. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  897. return hdb;
  898. }
  899. static void test_getcolinfo(void)
  900. {
  901. MSIHANDLE hdb, hview = 0, rec = 0;
  902. UINT r;
  903. DWORD sz;
  904. char buffer[0x20];
  905. /* create an empty db */
  906. hdb = create_db();
  907. ok( hdb, "failed to create db\n");
  908. /* tables should be present */
  909. r = MsiDatabaseOpenView(hdb, "select * from _Tables", &hview);
  910. ok( r == ERROR_SUCCESS, "failed to open query\n");
  911. r = MsiViewExecute(hview, 0);
  912. ok( r == ERROR_SUCCESS, "failed to execute query\n");
  913. /* check that NAMES works */
  914. rec = 0;
  915. r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
  916. ok( r == ERROR_SUCCESS, "failed to get names\n");
  917. sz = sizeof buffer;
  918. r = MsiRecordGetString(rec, 1, buffer, &sz );
  919. ok( r == ERROR_SUCCESS, "failed to get string\n");
  920. ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
  921. r = MsiCloseHandle( rec );
  922. ok( r == ERROR_SUCCESS, "failed to close record handle\n");
  923. /* check that TYPES works */
  924. rec = 0;
  925. r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
  926. ok( r == ERROR_SUCCESS, "failed to get names\n");
  927. sz = sizeof buffer;
  928. r = MsiRecordGetString(rec, 1, buffer, &sz );
  929. ok( r == ERROR_SUCCESS, "failed to get string\n");
  930. ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
  931. r = MsiCloseHandle( rec );
  932. ok( r == ERROR_SUCCESS, "failed to close record handle\n");
  933. /* check that invalid values fail */
  934. rec = 0;
  935. r = MsiViewGetColumnInfo( hview, 100, &rec );
  936. ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
  937. ok( rec == 0, "returned a record\n");
  938. r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
  939. ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
  940. r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
  941. ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
  942. r = MsiViewClose(hview);
  943. ok( r == ERROR_SUCCESS, "failed to close view\n");
  944. r = MsiCloseHandle(hview);
  945. ok( r == ERROR_SUCCESS, "failed to close view handle\n");
  946. r = MsiCloseHandle(hdb);
  947. ok( r == ERROR_SUCCESS, "failed to close database\n");
  948. }
  949. static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
  950. {
  951. MSIHANDLE hview = 0, rec = 0;
  952. UINT r;
  953. r = MsiDatabaseOpenView(hdb, query, &hview);
  954. if( r != ERROR_SUCCESS )
  955. return r;
  956. r = MsiViewExecute(hview, 0);
  957. if( r == ERROR_SUCCESS )
  958. {
  959. MsiViewGetColumnInfo( hview, type, &rec );
  960. }
  961. MsiViewClose(hview);
  962. MsiCloseHandle(hview);
  963. return rec;
  964. }
  965. static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
  966. {
  967. MSIHANDLE hview = 0, rec = 0;
  968. UINT r, type = 0;
  969. char query[0x100];
  970. sprintf(query, "select * from `_Columns` where `Table` = '%s'", table );
  971. r = MsiDatabaseOpenView(hdb, query, &hview);
  972. if( r != ERROR_SUCCESS )
  973. return r;
  974. r = MsiViewExecute(hview, 0);
  975. if( r == ERROR_SUCCESS )
  976. {
  977. while (1)
  978. {
  979. r = MsiViewFetch( hview, &rec );
  980. if( r != ERROR_SUCCESS)
  981. break;
  982. r = MsiRecordGetInteger( rec, 2 );
  983. if (r == field)
  984. type = MsiRecordGetInteger( rec, 4 );
  985. MsiCloseHandle( rec );
  986. }
  987. }
  988. MsiViewClose(hview);
  989. MsiCloseHandle(hview);
  990. return type;
  991. }
  992. static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
  993. {
  994. CHAR buffer[0x20];
  995. UINT r;
  996. DWORD sz;
  997. sz = sizeof buffer;
  998. r = MsiRecordGetString( rec, field, buffer, &sz );
  999. return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
  1000. }
  1001. static void test_viewgetcolumninfo(void)
  1002. {
  1003. MSIHANDLE hdb = 0, rec;
  1004. UINT r;
  1005. hdb = create_db();
  1006. ok( hdb, "failed to create db\n");
  1007. r = run_query( hdb, 0,
  1008. "CREATE TABLE `Properties` "
  1009. "( `Property` CHAR(255), "
  1010. " `Value` CHAR(1), "
  1011. " `Intvalue` INT, "
  1012. " `Integervalue` INTEGER, "
  1013. " `Shortvalue` SHORT, "
  1014. " `Longvalue` LONG, "
  1015. " `Longcharvalue` LONGCHAR "
  1016. " PRIMARY KEY `Property`)" );
  1017. ok( r == ERROR_SUCCESS , "Failed to create table\n" );
  1018. /* check the column types */
  1019. rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
  1020. ok( rec, "failed to get column info record\n" );
  1021. ok( check_record( rec, 1, "S255"), "wrong record type\n");
  1022. ok( check_record( rec, 2, "S1"), "wrong record type\n");
  1023. ok( check_record( rec, 3, "I2"), "wrong record type\n");
  1024. ok( check_record( rec, 4, "I2"), "wrong record type\n");
  1025. ok( check_record( rec, 5, "I2"), "wrong record type\n");
  1026. ok( check_record( rec, 6, "I4"), "wrong record type\n");
  1027. ok( check_record( rec, 7, "S0"), "wrong record type\n");
  1028. MsiCloseHandle( rec );
  1029. /* check the type in _Columns */
  1030. ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
  1031. ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
  1032. ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
  1033. ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
  1034. ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
  1035. ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
  1036. ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
  1037. /* now try the names */
  1038. rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
  1039. ok( rec, "failed to get column info record\n" );
  1040. ok( check_record( rec, 1, "Property"), "wrong record type\n");
  1041. ok( check_record( rec, 2, "Value"), "wrong record type\n");
  1042. ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
  1043. ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
  1044. ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
  1045. ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
  1046. ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
  1047. MsiCloseHandle( rec );
  1048. r = run_query( hdb, 0,
  1049. "CREATE TABLE `Binary` "
  1050. "( `Name` CHAR(255), `Data` OBJECT PRIMARY KEY `Name`)" );
  1051. ok( r == ERROR_SUCCESS , "Failed to create table\n" );
  1052. /* check the column types */
  1053. rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
  1054. ok( rec, "failed to get column info record\n" );
  1055. ok( check_record( rec, 1, "S255"), "wrong record type\n");
  1056. ok( check_record( rec, 2, "V0"), "wrong record type\n");
  1057. MsiCloseHandle( rec );
  1058. /* check the type in _Columns */
  1059. ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
  1060. ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
  1061. /* now try the names */
  1062. rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
  1063. ok( rec, "failed to get column info record\n" );
  1064. ok( check_record( rec, 1, "Name"), "wrong record type\n");
  1065. ok( check_record( rec, 2, "Data"), "wrong record type\n");
  1066. MsiCloseHandle( rec );
  1067. r = run_query( hdb, 0,
  1068. "CREATE TABLE `UIText` "
  1069. "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
  1070. ok( r == ERROR_SUCCESS , "Failed to create table\n" );
  1071. ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
  1072. ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
  1073. rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
  1074. ok( rec, "failed to get column info record\n" );
  1075. ok( check_record( rec, 1, "Key"), "wrong record type\n");
  1076. ok( check_record( rec, 2, "Text"), "wrong record type\n");
  1077. MsiCloseHandle( rec );
  1078. rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
  1079. ok( rec, "failed to get column info record\n" );
  1080. ok( check_record( rec, 1, "s72"), "wrong record type\n");
  1081. ok( check_record( rec, 2, "L255"), "wrong record type\n");
  1082. MsiCloseHandle( rec );
  1083. MsiCloseHandle( hdb );
  1084. }
  1085. static void test_msiexport(void)
  1086. {
  1087. MSIHANDLE hdb = 0, hview = 0;
  1088. UINT r;
  1089. const char *query;
  1090. char path[MAX_PATH];
  1091. const char file[] = "phone.txt";
  1092. HANDLE handle;
  1093. char buffer[0x100];
  1094. DWORD length;
  1095. const char expected[] =
  1096. "id\tname\tnumber\r\n"
  1097. "I2\tS32\tS32\r\n"
  1098. "phone\tid\r\n"
  1099. "1\tAbe\t8675309\r\n";
  1100. DeleteFile(msifile);
  1101. /* just MsiOpenDatabase should not create a file */
  1102. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  1103. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  1104. /* create a table */
  1105. query = "CREATE TABLE `phone` ( "
  1106. "`id` INT, `name` CHAR(32), `number` CHAR(32) "
  1107. "PRIMARY KEY `id`)";
  1108. r = MsiDatabaseOpenView(hdb, query, &hview);
  1109. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  1110. r = MsiViewExecute(hview, 0);
  1111. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  1112. r = MsiViewClose(hview);
  1113. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  1114. r = MsiCloseHandle(hview);
  1115. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  1116. /* insert a value into it */
  1117. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  1118. "VALUES('1', 'Abe', '8675309')";
  1119. r = MsiDatabaseOpenView(hdb, query, &hview);
  1120. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  1121. r = MsiViewExecute(hview, 0);
  1122. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  1123. r = MsiViewClose(hview);
  1124. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  1125. r = MsiCloseHandle(hview);
  1126. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  1127. GetCurrentDirectory(MAX_PATH, path);
  1128. r = MsiDatabaseExport(hdb, "phone", path, file);
  1129. ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
  1130. MsiCloseHandle(hdb);
  1131. lstrcat(path, "\\");
  1132. lstrcat(path, file);
  1133. /* check the data that was written */
  1134. length = 0;
  1135. memset(buffer, 0, sizeof buffer);
  1136. handle = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  1137. if (handle != INVALID_HANDLE_VALUE)
  1138. {
  1139. ReadFile(handle, buffer, sizeof buffer, &length, NULL);
  1140. CloseHandle(handle);
  1141. DeleteFile(path);
  1142. }
  1143. else
  1144. ok(0, "failed to open file %s\n", path);
  1145. ok( length == strlen(expected), "length of data wrong\n");
  1146. ok( !lstrcmp(buffer, expected), "data doesn't match\n");
  1147. DeleteFile(msifile);
  1148. }
  1149. static void test_longstrings(void)
  1150. {
  1151. const char insert_query[] =
  1152. "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
  1153. char *str;
  1154. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  1155. DWORD len;
  1156. UINT r;
  1157. const DWORD STRING_LENGTH = 0x10005;
  1158. DeleteFile(msifile);
  1159. /* just MsiOpenDatabase should not create a file */
  1160. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  1161. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  1162. /* create a table */
  1163. r = try_query( hdb,
  1164. "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
  1165. ok(r == ERROR_SUCCESS, "query failed\n");
  1166. /* try a insert a very long string */
  1167. str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
  1168. len = strchr(insert_query, 'Z') - insert_query;
  1169. strcpy(str, insert_query);
  1170. memset(str+len, 'Z', STRING_LENGTH);
  1171. strcpy(str+len+STRING_LENGTH, insert_query+len+1);
  1172. r = try_query( hdb, str );
  1173. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  1174. HeapFree(GetProcessHeap(), 0, str);
  1175. r = MsiDatabaseCommit(hdb);
  1176. ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
  1177. MsiCloseHandle(hdb);
  1178. r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
  1179. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  1180. r = MsiDatabaseOpenView(hdb, "select * from `strings` where `id` = 1", &hview);
  1181. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  1182. r = MsiViewExecute(hview, 0);
  1183. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  1184. r = MsiViewFetch(hview, &hrec);
  1185. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  1186. MsiViewClose(hview);
  1187. MsiCloseHandle(hview);
  1188. r = MsiRecordGetString(hrec, 2, NULL, &len);
  1189. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  1190. ok(len == STRING_LENGTH, "string length wrong\n");
  1191. MsiCloseHandle(hrec);
  1192. MsiCloseHandle(hdb);
  1193. DeleteFile(msifile);
  1194. }
  1195. static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
  1196. {
  1197. HANDLE file;
  1198. DWORD written;
  1199. file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
  1200. if (file == INVALID_HANDLE_VALUE)
  1201. return;
  1202. WriteFile(file, data, strlen(data), &written, NULL);
  1203. WriteFile(file, "\n", strlen("\n"), &written, NULL);
  1204. if (size)
  1205. {
  1206. SetFilePointer(file, size, NULL, FILE_BEGIN);
  1207. SetEndOfFile(file);
  1208. }
  1209. CloseHandle(file);
  1210. }
  1211. #define create_file(name) create_file_data(name, name, 0)
  1212. static void test_streamtable(void)
  1213. {
  1214. MSIHANDLE hdb = 0, rec, view, hsi;
  1215. char file[MAX_PATH];
  1216. char buf[MAX_PATH];
  1217. DWORD size;
  1218. UINT r;
  1219. hdb = create_db();
  1220. ok( hdb, "failed to create db\n");
  1221. r = run_query( hdb, 0,
  1222. "CREATE TABLE `Properties` "
  1223. "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" );
  1224. ok( r == ERROR_SUCCESS , "Failed to create table\n" );
  1225. r = run_query( hdb, 0,
  1226. "INSERT INTO `Properties` "
  1227. "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
  1228. ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
  1229. r = MsiDatabaseCommit( hdb );
  1230. ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
  1231. MsiCloseHandle( hdb );
  1232. r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
  1233. ok( r == ERROR_SUCCESS , "Failed to open database\n" );
  1234. /* check the column types */
  1235. rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
  1236. ok( rec, "failed to get column info record\n" );
  1237. ok( check_record( rec, 1, "s62"), "wrong record type\n");
  1238. ok( check_record( rec, 2, "V0"), "wrong record type\n");
  1239. MsiCloseHandle( rec );
  1240. /* now try the names */
  1241. rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
  1242. ok( rec, "failed to get column info record\n" );
  1243. ok( check_record( rec, 1, "Name"), "wrong record type\n");
  1244. ok( check_record( rec, 2, "Data"), "wrong record type\n");
  1245. MsiCloseHandle( rec );
  1246. r = MsiDatabaseOpenView( hdb,
  1247. "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
  1248. ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
  1249. r = MsiViewExecute( view, 0 );
  1250. ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
  1251. r = MsiViewFetch( view, &rec );
  1252. ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
  1253. MsiCloseHandle( rec );
  1254. MsiViewClose( view );
  1255. MsiCloseHandle( view );
  1256. /* create a summary information stream */
  1257. r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
  1258. ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
  1259. r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
  1260. ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
  1261. r = MsiSummaryInfoPersist( hsi );
  1262. ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
  1263. MsiCloseHandle( hsi );
  1264. r = MsiDatabaseOpenView( hdb,
  1265. "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
  1266. ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
  1267. r = MsiViewExecute( view, 0 );
  1268. ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
  1269. r = MsiViewFetch( view, &rec );
  1270. ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
  1271. MsiCloseHandle( rec );
  1272. MsiViewClose( view );
  1273. MsiCloseHandle( view );
  1274. /* insert a file into the _Streams table */
  1275. create_file( "test.txt" );
  1276. rec = MsiCreateRecord( 2 );
  1277. MsiRecordSetString( rec, 1, "data" );
  1278. r = MsiRecordSetStream( rec, 2, "test.txt" );
  1279. ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
  1280. DeleteFile("test.txt");
  1281. r = MsiDatabaseOpenView( hdb,
  1282. "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
  1283. ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
  1284. r = MsiViewExecute( view, rec );
  1285. ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
  1286. MsiCloseHandle( rec );
  1287. MsiViewClose( view );
  1288. MsiCloseHandle( view );
  1289. /* insert another one */
  1290. create_file( "test1.txt" );
  1291. rec = MsiCreateRecord( 2 );
  1292. MsiRecordSetString( rec, 1, "data1" );
  1293. r = MsiRecordSetStream( rec, 2, "test1.txt" );
  1294. ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
  1295. DeleteFile("test1.txt");
  1296. r = MsiDatabaseOpenView( hdb,
  1297. "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
  1298. ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
  1299. r = MsiViewExecute( view, rec );
  1300. ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
  1301. MsiCloseHandle( rec );
  1302. MsiViewClose( view );
  1303. MsiCloseHandle( view );
  1304. r = MsiDatabaseOpenView( hdb,
  1305. "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
  1306. ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
  1307. r = MsiViewExecute( view, 0 );
  1308. ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
  1309. r = MsiViewFetch( view, &rec );
  1310. ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
  1311. size = MAX_PATH;
  1312. r = MsiRecordGetString( rec, 1, file, &size );
  1313. ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
  1314. ok( !lstrcmp(file, "data"), "Expected 'data', got %s\n", file);
  1315. size = MAX_PATH;
  1316. memset(buf, 0, MAX_PATH);
  1317. r = MsiRecordReadStream( rec, 2, buf, &size );
  1318. ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
  1319. ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf);
  1320. MsiCloseHandle( rec );
  1321. MsiViewClose( view );
  1322. MsiCloseHandle( view );
  1323. r = MsiDatabaseOpenView( hdb,
  1324. "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
  1325. ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
  1326. r = MsiViewExecute( view, 0 );
  1327. ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
  1328. r = MsiViewFetch( view, &rec );
  1329. ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1330. size = MAX_PATH;
  1331. r = MsiRecordGetString( rec, 1, file, &size );
  1332. ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
  1333. ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
  1334. size = MAX_PATH;
  1335. memset(buf, 0, MAX_PATH);
  1336. r = MsiRecordReadStream( rec, 2, buf, &size );
  1337. ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
  1338. ok( !lstrcmp(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
  1339. MsiCloseHandle( rec );
  1340. MsiViewClose( view );
  1341. MsiCloseHandle( view );
  1342. /* perform an update */
  1343. create_file( "test2.txt" );
  1344. rec = MsiCreateRecord( 1 );
  1345. r = MsiRecordSetStream( rec, 1, "test2.txt" );
  1346. ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
  1347. DeleteFile("test2.txt");
  1348. r = MsiDatabaseOpenView( hdb,
  1349. "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
  1350. ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
  1351. r = MsiViewExecute( view, rec );
  1352. ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
  1353. MsiCloseHandle( rec );
  1354. MsiViewClose( view );
  1355. MsiCloseHandle( view );
  1356. r = MsiDatabaseOpenView( hdb,
  1357. "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
  1358. ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
  1359. r = MsiViewExecute( view, 0 );
  1360. ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
  1361. r = MsiViewFetch( view, &rec );
  1362. ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
  1363. size = MAX_PATH;
  1364. r = MsiRecordGetString( rec, 1, file, &size );
  1365. ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
  1366. ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
  1367. size = MAX_PATH;
  1368. memset(buf, 0, MAX_PATH);
  1369. r = MsiRecordReadStream( rec, 2, buf, &size );
  1370. ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
  1371. todo_wine ok( !lstrcmp(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
  1372. MsiCloseHandle( rec );
  1373. MsiViewClose( view );
  1374. MsiCloseHandle( view );
  1375. MsiCloseHandle( hdb );
  1376. DeleteFile(msifile);
  1377. }
  1378. static void test_binary(void)
  1379. {
  1380. MSIHANDLE hdb = 0, rec;
  1381. char file[MAX_PATH];
  1382. char buf[MAX_PATH];
  1383. DWORD size;
  1384. LPCSTR query;
  1385. UINT r;
  1386. /* insert a file into the Binary table */
  1387. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
  1388. ok( r == ERROR_SUCCESS , "Failed to open database\n" );
  1389. query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)";
  1390. r = run_query( hdb, 0, query );
  1391. ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
  1392. create_file( "test.txt" );
  1393. rec = MsiCreateRecord( 1 );
  1394. r = MsiRecordSetStream( rec, 1, "test.txt" );
  1395. ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
  1396. DeleteFile( "test.txt" );
  1397. query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
  1398. r = run_query( hdb, rec, query );
  1399. ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
  1400. r = MsiCloseHandle( rec );
  1401. ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
  1402. r = MsiDatabaseCommit( hdb );
  1403. ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
  1404. r = MsiCloseHandle( hdb );
  1405. ok( r == ERROR_SUCCESS , "Failed to close database\n" );
  1406. /* read file from the Stream table */
  1407. r = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
  1408. ok( r == ERROR_SUCCESS , "Failed to open database\n" );
  1409. query = "SELECT * FROM `_Streams`";
  1410. r = do_query( hdb, query, &rec );
  1411. ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
  1412. size = MAX_PATH;
  1413. r = MsiRecordGetString( rec, 1, file, &size );
  1414. ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
  1415. ok( !lstrcmp(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
  1416. size = MAX_PATH;
  1417. memset( buf, 0, MAX_PATH );
  1418. r = MsiRecordReadStream( rec, 2, buf, &size );
  1419. ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
  1420. ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
  1421. r = MsiCloseHandle( rec );
  1422. ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
  1423. /* read file from the Binary table */
  1424. query = "SELECT * FROM `Binary`";
  1425. r = do_query( hdb, query, &rec );
  1426. ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
  1427. size = MAX_PATH;
  1428. r = MsiRecordGetString( rec, 1, file, &size );
  1429. ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
  1430. ok( !lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file );
  1431. size = MAX_PATH;
  1432. memset( buf, 0, MAX_PATH );
  1433. r = MsiRecordReadStream( rec, 3, buf, &size );
  1434. ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
  1435. ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
  1436. r = MsiCloseHandle( rec );
  1437. ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
  1438. r = MsiCloseHandle( hdb );
  1439. ok( r == ERROR_SUCCESS , "Failed to close database\n" );
  1440. DeleteFile( msifile );
  1441. }
  1442. static void test_where_not_in_selected(void)
  1443. {
  1444. MSIHANDLE hdb = 0, rec, view;
  1445. LPCSTR query;
  1446. UINT r;
  1447. hdb = create_db();
  1448. ok( hdb, "failed to create db\n");
  1449. r = run_query(hdb, 0,
  1450. "CREATE TABLE `IESTable` ("
  1451. "`Action` CHAR(64), "
  1452. "`Condition` CHAR(64), "
  1453. "`Sequence` LONG PRIMARY KEY `Sequence`)");
  1454. ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
  1455. r = run_query(hdb, 0,
  1456. "CREATE TABLE `CATable` ("
  1457. "`Action` CHAR(64), "
  1458. "`Type` LONG PRIMARY KEY `Type`)");
  1459. ok( r == S_OK, "Cannot create CATable table: %d\n", r);
  1460. r = run_query(hdb, 0, "INSERT INTO `IESTable` "
  1461. "( `Action`, `Condition`, `Sequence`) "
  1462. "VALUES ( 'clean', 'cond4', 4)");
  1463. ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
  1464. r = run_query(hdb, 0, "INSERT INTO `IESTable` "
  1465. "( `Action`, `Condition`, `Sequence`) "
  1466. "VALUES ( 'depends', 'cond1', 1)");
  1467. ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
  1468. r = run_query(hdb, 0, "INSERT INTO `IESTable` "
  1469. "( `Action`, `Condition`, `Sequence`) "
  1470. "VALUES ( 'build', 'cond2', 2)");
  1471. ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
  1472. r = run_query(hdb, 0, "INSERT INTO `IESTable` "
  1473. "( `Action`, `Condition`, `Sequence`) "
  1474. "VALUES ( 'build2', 'cond6', 6)");
  1475. ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
  1476. r = run_query(hdb, 0, "INSERT INTO `IESTable` "
  1477. "( `Action`, `Condition`, `Sequence`) "
  1478. "VALUES ( 'build', 'cond3', 3)");
  1479. ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
  1480. r = run_query(hdb, 0, "INSERT INTO `CATable` "
  1481. "( `Action`, `Type` ) "
  1482. "VALUES ( 'build', 32)");
  1483. ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
  1484. r = run_query(hdb, 0, "INSERT INTO `CATable` "
  1485. "( `Action`, `Type` ) "
  1486. "VALUES ( 'depends', 64)");
  1487. ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
  1488. r = run_query(hdb, 0, "INSERT INTO `CATable` "
  1489. "( `Action`, `Type` ) "
  1490. "VALUES ( 'clean', 63)");
  1491. ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
  1492. r = run_query(hdb, 0, "INSERT INTO `CATable` "
  1493. "( `Action`, `Type` ) "
  1494. "VALUES ( 'build2', 34)");
  1495. ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
  1496. query = "Select IESTable.Condition from CATable, IESTable where "
  1497. "CATable.Action = IESTable.Action and CATable.Type = 32";
  1498. r = MsiDatabaseOpenView(hdb, query, &view);
  1499. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  1500. r = MsiViewExecute(view, 0);
  1501. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  1502. r = MsiViewFetch(view, &rec);
  1503. ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
  1504. ok( check_record( rec, 1, "cond2"), "wrong condition\n");
  1505. MsiCloseHandle( rec );
  1506. r = MsiViewFetch(view, &rec);
  1507. ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
  1508. ok( check_record( rec, 1, "cond3"), "wrong condition\n");
  1509. MsiCloseHandle( rec );
  1510. MsiViewClose(view);
  1511. MsiCloseHandle(view);
  1512. MsiCloseHandle( hdb );
  1513. DeleteFile(msifile);
  1514. }
  1515. static void test_where(void)
  1516. {
  1517. MSIHANDLE hdb = 0, rec, view;
  1518. LPCSTR query;
  1519. UINT r;
  1520. DWORD size;
  1521. CHAR buf[MAX_PATH];
  1522. UINT count;
  1523. hdb = create_db();
  1524. ok( hdb, "failed to create db\n");
  1525. r = run_query( hdb, 0,
  1526. "CREATE TABLE `Media` ("
  1527. "`DiskId` SHORT NOT NULL, "
  1528. "`LastSequence` LONG, "
  1529. "`DiskPrompt` CHAR(64) LOCALIZABLE, "
  1530. "`Cabinet` CHAR(255), "
  1531. "`VolumeLabel` CHAR(32), "
  1532. "`Source` CHAR(72) "
  1533. "PRIMARY KEY `DiskId`)" );
  1534. ok( r == S_OK, "cannot create Media table: %d\n", r );
  1535. r = run_query( hdb, 0, "INSERT INTO `Media` "
  1536. "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
  1537. "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
  1538. ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
  1539. r = run_query( hdb, 0, "INSERT INTO `Media` "
  1540. "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
  1541. "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
  1542. ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
  1543. r = run_query( hdb, 0, "INSERT INTO `Media` "
  1544. "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
  1545. "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
  1546. ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
  1547. query = "SELECT * FROM `Media`";
  1548. r = do_query(hdb, query, &rec);
  1549. ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
  1550. ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
  1551. MsiCloseHandle( rec );
  1552. query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
  1553. r = do_query(hdb, query, &rec);
  1554. ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
  1555. ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
  1556. r = MsiRecordGetInteger(rec, 1);
  1557. ok( 2 == r, "field wrong\n");
  1558. r = MsiRecordGetInteger(rec, 2);
  1559. ok( 1 == r, "field wrong\n");
  1560. MsiCloseHandle( rec );
  1561. query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
  1562. r = MsiDatabaseOpenView(hdb, query, &view);
  1563. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  1564. r = MsiViewExecute(view, 0);
  1565. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  1566. r = MsiViewFetch(view, &rec);
  1567. ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
  1568. count = MsiRecordGetFieldCount( rec );
  1569. ok( count == 1, "Expected 1 record fields, got %d\n", count );
  1570. size = MAX_PATH;
  1571. r = MsiRecordGetString( rec, 1, buf, &size );
  1572. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  1573. ok( !lstrcmp( buf, "2" ),
  1574. "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
  1575. MsiCloseHandle( rec );
  1576. r = MsiViewFetch(view, &rec);
  1577. ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
  1578. size = MAX_PATH;
  1579. r = MsiRecordGetString( rec, 1, buf, &size );
  1580. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  1581. ok( !lstrcmp( buf, "3" ),
  1582. "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
  1583. MsiCloseHandle( rec );
  1584. r = MsiViewFetch(view, &rec);
  1585. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  1586. MsiViewClose(view);
  1587. MsiCloseHandle(view);
  1588. MsiCloseHandle( rec );
  1589. rec = 0;
  1590. query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
  1591. r = do_query(hdb, query, &rec);
  1592. ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
  1593. MsiCloseHandle( rec );
  1594. rec = 0;
  1595. query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
  1596. r = do_query(hdb, query, &rec);
  1597. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
  1598. MsiCloseHandle( rec );
  1599. rec = 0;
  1600. query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
  1601. r = do_query(hdb, query, &rec);
  1602. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
  1603. MsiCloseHandle( rec );
  1604. rec = 0;
  1605. query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
  1606. r = do_query(hdb, query, &rec);
  1607. ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
  1608. MsiCloseHandle( rec );
  1609. rec = 0;
  1610. query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
  1611. r = do_query(hdb, query, &rec);
  1612. ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
  1613. MsiCloseHandle( rec );
  1614. rec = MsiCreateRecord(1);
  1615. MsiRecordSetString(rec, 1, "");
  1616. query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
  1617. r = MsiDatabaseOpenView(hdb, query, &view);
  1618. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1619. r = MsiViewExecute(view, rec);
  1620. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1621. MsiCloseHandle(rec);
  1622. r = MsiViewFetch(view, &rec);
  1623. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1624. MsiCloseHandle(rec);
  1625. MsiViewClose(view);
  1626. MsiCloseHandle(view);
  1627. MsiCloseHandle( hdb );
  1628. DeleteFile(msifile);
  1629. }
  1630. static CHAR CURR_DIR[MAX_PATH];
  1631. static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
  1632. "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
  1633. "TestTable\tFirstPrimaryColumn\n"
  1634. "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
  1635. static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
  1636. "s255\ts255\n"
  1637. "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
  1638. "papaya\tleaf\n"
  1639. "papaya\tflower\n";
  1640. static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
  1641. "s72\ts72\ts72\ts72\ts72\ts72\n"
  1642. "Table\tA\r\n"
  1643. "a\tb\tc\td\te\tf\n"
  1644. "g\th\ti\t\rj\tk\tl\r\n";
  1645. static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
  1646. "s72\ts72\ts72\ts72\ts72\ts72\n"
  1647. "Table2\tA\r\n"
  1648. "a\tb\tc\td\te\tf\n"
  1649. "g\th\ti\tj\tk\tl\r\n";
  1650. static const CHAR suminfo[] = "PropertyId\tValue\n"
  1651. "i2\tl255\n"
  1652. "_SummaryInformation\tPropertyId\n"
  1653. "1\t1252\n"
  1654. "2\tInstaller Database\n"
  1655. "3\tInstaller description\n"
  1656. "4\tWineHQ\n"
  1657. "5\tInstaller\n"
  1658. "6\tInstaller comments\n"
  1659. "7\tIntel;1033,2057\n"
  1660. "9\t{12345678-1234-1234-1234-123456789012}\n"
  1661. "12\t2009/04/12 15:46:11\n"
  1662. "13\t2009/04/12 15:46:11\n"
  1663. "14\t200\n"
  1664. "15\t2\n"
  1665. "18\tVim\n"
  1666. "19\t2\n";
  1667. static void write_file(const CHAR *filename, const char *data, int data_size)
  1668. {
  1669. DWORD size;
  1670. HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
  1671. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1672. WriteFile(hf, data, data_size, &size, NULL);
  1673. CloseHandle(hf);
  1674. }
  1675. static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
  1676. {
  1677. UINT r;
  1678. write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
  1679. r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
  1680. DeleteFileA("temp_file");
  1681. return r;
  1682. }
  1683. static void test_suminfo_import(void)
  1684. {
  1685. MSIHANDLE hdb, hsi, view = 0;
  1686. LPCSTR query;
  1687. UINT r, count, size, type;
  1688. char str_value[50];
  1689. INT int_value;
  1690. FILETIME ft_value;
  1691. GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
  1692. r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
  1693. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1694. r = add_table_to_db(hdb, suminfo);
  1695. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1696. /* _SummaryInformation is not imported as a regular table... */
  1697. query = "SELECT * FROM `_SummaryInformation`";
  1698. r = MsiDatabaseOpenViewA(hdb, query, &view);
  1699. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
  1700. MsiCloseHandle(view);
  1701. /* ...its data is added to the special summary information stream */
  1702. r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
  1703. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1704. r = MsiSummaryInfoGetPropertyCount(hsi, &count);
  1705. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1706. ok(count == 14, "Expected 14, got %u\n", count);
  1707. r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
  1708. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1709. ok(type == VT_I2, "Expected VT_I2, got %u\n", type);
  1710. ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
  1711. size = sizeof(str_value);
  1712. r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
  1713. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1714. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1715. ok(size == 18, "Expected 18, got %u\n", size);
  1716. ok(!strcmp(str_value, "Installer Database"),
  1717. "Expected \"Installer Database\", got %s\n", str_value);
  1718. size = sizeof(str_value);
  1719. r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
  1720. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1721. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1722. ok(!strcmp(str_value, "Installer description"),
  1723. "Expected \"Installer description\", got %s\n", str_value);
  1724. size = sizeof(str_value);
  1725. r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
  1726. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1727. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1728. ok(!strcmp(str_value, "WineHQ"),
  1729. "Expected \"WineHQ\", got %s\n", str_value);
  1730. size = sizeof(str_value);
  1731. r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
  1732. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1733. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1734. ok(!strcmp(str_value, "Installer"),
  1735. "Expected \"Installer\", got %s\n", str_value);
  1736. size = sizeof(str_value);
  1737. r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
  1738. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1739. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1740. ok(!strcmp(str_value, "Installer comments"),
  1741. "Expected \"Installer comments\", got %s\n", str_value);
  1742. size = sizeof(str_value);
  1743. r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
  1744. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1745. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1746. ok(!strcmp(str_value, "Intel;1033,2057"),
  1747. "Expected \"Intel;1033,2057\", got %s\n", str_value);
  1748. size = sizeof(str_value);
  1749. r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
  1750. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1751. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1752. ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
  1753. "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
  1754. r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
  1755. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1756. ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
  1757. r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
  1758. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1759. ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
  1760. r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
  1761. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1762. ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
  1763. ok(int_value == 200, "Expected 200, got %d\n", int_value);
  1764. r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
  1765. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1766. ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
  1767. ok(int_value == 2, "Expected 2, got %d\n", int_value);
  1768. r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
  1769. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1770. ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
  1771. ok(int_value == 2, "Expected 2, got %d\n", int_value);
  1772. size = sizeof(str_value);
  1773. r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
  1774. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  1775. ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
  1776. ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
  1777. MsiCloseHandle(hsi);
  1778. MsiCloseHandle(hdb);
  1779. DeleteFileA(msifile);
  1780. }
  1781. static void test_msiimport(void)
  1782. {
  1783. MSIHANDLE hdb, view, rec;
  1784. LPCSTR query;
  1785. UINT r, count;
  1786. signed int i;
  1787. GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
  1788. r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
  1789. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1790. r = add_table_to_db(hdb, test_data);
  1791. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1792. r = add_table_to_db(hdb, two_primary);
  1793. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1794. r = add_table_to_db(hdb, endlines1);
  1795. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1796. r = add_table_to_db(hdb, endlines2);
  1797. ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  1798. query = "SELECT * FROM `TestTable`";
  1799. r = MsiDatabaseOpenView(hdb, query, &view);
  1800. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1801. r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
  1802. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1803. count = MsiRecordGetFieldCount(rec);
  1804. ok(count == 9, "Expected 9, got %d\n", count);
  1805. ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
  1806. ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
  1807. ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
  1808. ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
  1809. ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
  1810. ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
  1811. ok(check_record(rec, 7, "String"), "Expected String\n");
  1812. ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
  1813. ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
  1814. MsiCloseHandle(rec);
  1815. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  1816. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1817. count = MsiRecordGetFieldCount(rec);
  1818. ok(count == 9, "Expected 9, got %d\n", count);
  1819. ok(check_record(rec, 1, "s255"), "Expected s255\n");
  1820. ok(check_record(rec, 2, "i2"), "Expected i2\n");
  1821. ok(check_record(rec, 3, "i2"), "Expected i2\n");
  1822. ok(check_record(rec, 4, "I2"), "Expected I2\n");
  1823. ok(check_record(rec, 5, "i4"), "Expected i4\n");
  1824. ok(check_record(rec, 6, "I4"), "Expected I4\n");
  1825. ok(check_record(rec, 7, "S255"), "Expected S255\n");
  1826. ok(check_record(rec, 8, "S0"), "Expected S0\n");
  1827. ok(check_record(rec, 9, "s0"), "Expected s0\n");
  1828. MsiCloseHandle(rec);
  1829. query = "SELECT * FROM `TestTable`";
  1830. r = do_query(hdb, query, &rec);
  1831. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1832. ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
  1833. ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
  1834. ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
  1835. ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
  1836. i = MsiRecordGetInteger(rec, 2);
  1837. ok(i == 5, "Expected 5, got %d\n", i);
  1838. i = MsiRecordGetInteger(rec, 3);
  1839. ok(i == 2, "Expected 2, got %d\n", i);
  1840. i = MsiRecordGetInteger(rec, 4);
  1841. ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
  1842. i = MsiRecordGetInteger(rec, 5);
  1843. ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
  1844. i = MsiRecordGetInteger(rec, 6);
  1845. ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
  1846. MsiCloseHandle(rec);
  1847. MsiViewClose(view);
  1848. MsiCloseHandle(view);
  1849. query = "SELECT * FROM `TwoPrimary`";
  1850. r = MsiDatabaseOpenView(hdb, query, &view);
  1851. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1852. r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
  1853. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1854. count = MsiRecordGetFieldCount(rec);
  1855. ok(count == 2, "Expected 2, got %d\n", count);
  1856. ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
  1857. ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
  1858. MsiCloseHandle(rec);
  1859. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  1860. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1861. count = MsiRecordGetFieldCount(rec);
  1862. ok(count == 2, "Expected 2, got %d\n", count);
  1863. ok(check_record(rec, 1, "s255"), "Expected s255\n");
  1864. ok(check_record(rec, 2, "s255"), "Expected s255\n");
  1865. MsiCloseHandle(rec);
  1866. r = MsiViewExecute(view, 0);
  1867. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1868. r = MsiViewFetch(view, &rec);
  1869. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1870. ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
  1871. ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
  1872. MsiCloseHandle(rec);
  1873. r = MsiViewFetch(view, &rec);
  1874. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1875. ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
  1876. ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
  1877. MsiCloseHandle(rec);
  1878. r = MsiViewFetch(view, &rec);
  1879. ok(r == ERROR_NO_MORE_ITEMS,
  1880. "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  1881. r = MsiViewClose(view);
  1882. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1883. MsiCloseHandle(view);
  1884. query = "SELECT * FROM `Table`";
  1885. r = MsiDatabaseOpenView(hdb, query, &view);
  1886. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1887. r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
  1888. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1889. count = MsiRecordGetFieldCount(rec);
  1890. ok(count == 6, "Expected 6, got %d\n", count);
  1891. ok(check_record(rec, 1, "A"), "Expected A\n");
  1892. ok(check_record(rec, 2, "B"), "Expected B\n");
  1893. ok(check_record(rec, 3, "C"), "Expected C\n");
  1894. ok(check_record(rec, 4, "D"), "Expected D\n");
  1895. ok(check_record(rec, 5, "E"), "Expected E\n");
  1896. ok(check_record(rec, 6, "F"), "Expected F\n");
  1897. MsiCloseHandle(rec);
  1898. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  1899. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1900. count = MsiRecordGetFieldCount(rec);
  1901. ok(count == 6, "Expected 6, got %d\n", count);
  1902. ok(check_record(rec, 1, "s72"), "Expected s72\n");
  1903. ok(check_record(rec, 2, "s72"), "Expected s72\n");
  1904. ok(check_record(rec, 3, "s72"), "Expected s72\n");
  1905. ok(check_record(rec, 4, "s72"), "Expected s72\n");
  1906. ok(check_record(rec, 5, "s72"), "Expected s72\n");
  1907. ok(check_record(rec, 6, "s72"), "Expected s72\n");
  1908. MsiCloseHandle(rec);
  1909. MsiViewClose(view);
  1910. MsiCloseHandle(view);
  1911. query = "SELECT * FROM `Table`";
  1912. r = MsiDatabaseOpenView(hdb, query, &view);
  1913. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1914. r = MsiViewExecute(view, 0);
  1915. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1916. r = MsiViewFetch(view, &rec);
  1917. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1918. ok(check_record(rec, 1, "a"), "Expected 'a'\n");
  1919. ok(check_record(rec, 2, "b"), "Expected 'b'\n");
  1920. ok(check_record(rec, 3, "c"), "Expected 'c'\n");
  1921. ok(check_record(rec, 4, "d"), "Expected 'd'\n");
  1922. ok(check_record(rec, 5, "e"), "Expected 'e'\n");
  1923. ok(check_record(rec, 6, "f"), "Expected 'f'\n");
  1924. MsiCloseHandle(rec);
  1925. r = MsiViewFetch(view, &rec);
  1926. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  1927. ok(check_record(rec, 1, "g"), "Expected 'g'\n");
  1928. ok(check_record(rec, 2, "h"), "Expected 'h'\n");
  1929. ok(check_record(rec, 3, "i"), "Expected 'i'\n");
  1930. ok(check_record(rec, 4, "j"), "Expected 'j'\n");
  1931. ok(check_record(rec, 5, "k"), "Expected 'k'\n");
  1932. ok(check_record(rec, 6, "l"), "Expected 'l'\n");
  1933. MsiCloseHandle(rec);
  1934. r = MsiViewFetch(view, &rec);
  1935. ok(r == ERROR_NO_MORE_ITEMS,
  1936. "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  1937. MsiViewClose(view);
  1938. MsiCloseHandle(view);
  1939. MsiCloseHandle(hdb);
  1940. DeleteFileA(msifile);
  1941. }
  1942. static const CHAR bin_import_dat[] = "Name\tData\r\n"
  1943. "s72\tV0\r\n"
  1944. "Binary\tName\r\n"
  1945. "filename1\tfilename1.ibd\r\n";
  1946. static void test_binary_import(void)
  1947. {
  1948. MSIHANDLE hdb = 0, rec;
  1949. char file[MAX_PATH];
  1950. char buf[MAX_PATH];
  1951. char path[MAX_PATH];
  1952. DWORD size;
  1953. LPCSTR query;
  1954. UINT r;
  1955. /* create files to import */
  1956. write_file("bin_import.idt", bin_import_dat,
  1957. (sizeof(bin_import_dat) - 1) * sizeof(char));
  1958. CreateDirectory("bin_import", NULL);
  1959. create_file_data("bin_import/filename1.ibd", "just some words", 15);
  1960. /* import files into database */
  1961. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  1962. ok( r == ERROR_SUCCESS , "Failed to open database\n");
  1963. GetCurrentDirectory(MAX_PATH, path);
  1964. r = MsiDatabaseImport(hdb, path, "bin_import.idt");
  1965. ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
  1966. /* read file from the Binary table */
  1967. query = "SELECT * FROM `Binary`";
  1968. r = do_query(hdb, query, &rec);
  1969. ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
  1970. size = MAX_PATH;
  1971. r = MsiRecordGetString(rec, 1, file, &size);
  1972. ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
  1973. ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file);
  1974. size = MAX_PATH;
  1975. memset(buf, 0, MAX_PATH);
  1976. r = MsiRecordReadStream(rec, 2, buf, &size);
  1977. ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
  1978. ok(!lstrcmp(buf, "just some words"),
  1979. "Expected 'just some words', got %s\n", buf);
  1980. r = MsiCloseHandle(rec);
  1981. ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
  1982. r = MsiCloseHandle(hdb);
  1983. ok(r == ERROR_SUCCESS , "Failed to close database\n");
  1984. DeleteFile("bin_import/filename1.ibd");
  1985. RemoveDirectory("bin_import");
  1986. DeleteFile("bin_import.idt");
  1987. }
  1988. static void test_markers(void)
  1989. {
  1990. MSIHANDLE hdb, rec;
  1991. LPCSTR query;
  1992. UINT r;
  1993. hdb = create_db();
  1994. ok( hdb, "failed to create db\n");
  1995. rec = MsiCreateRecord(3);
  1996. MsiRecordSetString(rec, 1, "Table");
  1997. MsiRecordSetString(rec, 2, "Apples");
  1998. MsiRecordSetString(rec, 3, "Oranges");
  1999. /* try a legit create */
  2000. query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
  2001. r = run_query(hdb, 0, query);
  2002. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2003. MsiCloseHandle(rec);
  2004. /* try table name as marker */
  2005. rec = MsiCreateRecord(1);
  2006. MsiRecordSetString(rec, 1, "Fable");
  2007. query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
  2008. r = run_query(hdb, rec, query);
  2009. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2010. /* verify that we just created a table called '?', not 'Fable' */
  2011. r = try_query(hdb, "SELECT * from `Fable`");
  2012. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2013. r = try_query(hdb, "SELECT * from `?`");
  2014. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2015. /* try table name as marker without backticks */
  2016. MsiRecordSetString(rec, 1, "Mable");
  2017. query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
  2018. r = run_query(hdb, rec, query);
  2019. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2020. /* try one column name as marker */
  2021. MsiRecordSetString(rec, 1, "One");
  2022. query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
  2023. r = run_query(hdb, rec, query);
  2024. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2025. MsiCloseHandle(rec);
  2026. /* try column names as markers */
  2027. rec = MsiCreateRecord(2);
  2028. MsiRecordSetString(rec, 1, "One");
  2029. MsiRecordSetString(rec, 2, "Two");
  2030. query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
  2031. r = run_query(hdb, rec, query);
  2032. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2033. MsiCloseHandle(rec);
  2034. /* try names with backticks */
  2035. rec = MsiCreateRecord(3);
  2036. MsiRecordSetString(rec, 1, "One");
  2037. MsiRecordSetString(rec, 2, "Two");
  2038. MsiRecordSetString(rec, 3, "One");
  2039. query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
  2040. r = run_query(hdb, rec, query);
  2041. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2042. /* try names with backticks, minus definitions */
  2043. query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
  2044. r = run_query(hdb, rec, query);
  2045. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2046. /* try names without backticks */
  2047. query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
  2048. r = run_query(hdb, rec, query);
  2049. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2050. MsiCloseHandle(rec);
  2051. /* try one long marker */
  2052. rec = MsiCreateRecord(1);
  2053. MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
  2054. query = "CREATE TABLE `Mable` ( ? )";
  2055. r = run_query(hdb, rec, query);
  2056. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2057. MsiCloseHandle(rec);
  2058. /* try all names as markers */
  2059. rec = MsiCreateRecord(4);
  2060. MsiRecordSetString(rec, 1, "Mable");
  2061. MsiRecordSetString(rec, 2, "One");
  2062. MsiRecordSetString(rec, 3, "Two");
  2063. MsiRecordSetString(rec, 4, "One");
  2064. query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
  2065. r = run_query(hdb, rec, query);
  2066. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2067. MsiCloseHandle(rec);
  2068. /* try a legit insert */
  2069. query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
  2070. r = run_query(hdb, 0, query);
  2071. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2072. r = try_query(hdb, "SELECT * from `Table`");
  2073. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2074. /* try values as markers */
  2075. rec = MsiCreateRecord(2);
  2076. MsiRecordSetInteger(rec, 1, 4);
  2077. MsiRecordSetString(rec, 2, "hi");
  2078. query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
  2079. r = run_query(hdb, rec, query);
  2080. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2081. MsiCloseHandle(rec);
  2082. /* try column names and values as markers */
  2083. rec = MsiCreateRecord(4);
  2084. MsiRecordSetString(rec, 1, "One");
  2085. MsiRecordSetString(rec, 2, "Two");
  2086. MsiRecordSetInteger(rec, 3, 5);
  2087. MsiRecordSetString(rec, 4, "hi");
  2088. query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
  2089. r = run_query(hdb, rec, query);
  2090. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2091. MsiCloseHandle(rec);
  2092. /* try column names as markers */
  2093. rec = MsiCreateRecord(2);
  2094. MsiRecordSetString(rec, 1, "One");
  2095. MsiRecordSetString(rec, 2, "Two");
  2096. query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
  2097. r = run_query(hdb, rec, query);
  2098. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2099. MsiCloseHandle(rec);
  2100. /* try table name as a marker */
  2101. rec = MsiCreateRecord(1);
  2102. MsiRecordSetString(rec, 1, "Table");
  2103. query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
  2104. r = run_query(hdb, rec, query);
  2105. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2106. MsiCloseHandle(rec);
  2107. /* try table name and values as markers */
  2108. rec = MsiCreateRecord(3);
  2109. MsiRecordSetString(rec, 1, "Table");
  2110. MsiRecordSetInteger(rec, 2, 10);
  2111. MsiRecordSetString(rec, 3, "haha");
  2112. query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
  2113. r = run_query(hdb, rec, query);
  2114. ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  2115. MsiCloseHandle(rec);
  2116. /* try all markers */
  2117. rec = MsiCreateRecord(5);
  2118. MsiRecordSetString(rec, 1, "Table");
  2119. MsiRecordSetString(rec, 1, "One");
  2120. MsiRecordSetString(rec, 1, "Two");
  2121. MsiRecordSetInteger(rec, 2, 10);
  2122. MsiRecordSetString(rec, 3, "haha");
  2123. query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
  2124. r = run_query(hdb, rec, query);
  2125. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  2126. MsiCloseHandle(rec);
  2127. /* insert an integer as a string */
  2128. rec = MsiCreateRecord(2);
  2129. MsiRecordSetString(rec, 1, "11");
  2130. MsiRecordSetString(rec, 2, "hi");
  2131. query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
  2132. r = run_query(hdb, rec, query);
  2133. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2134. MsiCloseHandle(rec);
  2135. /* leave off the '' for the string */
  2136. rec = MsiCreateRecord(2);
  2137. MsiRecordSetInteger(rec, 1, 12);
  2138. MsiRecordSetString(rec, 2, "hi");
  2139. query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
  2140. r = run_query(hdb, rec, query);
  2141. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2142. MsiCloseHandle(rec);
  2143. MsiCloseHandle(hdb);
  2144. DeleteFileA(msifile);
  2145. }
  2146. #define MY_NVIEWS 4000 /* Largest installer I've seen uses < 2k */
  2147. static void test_handle_limit(void)
  2148. {
  2149. int i;
  2150. MSIHANDLE hdb;
  2151. MSIHANDLE hviews[MY_NVIEWS];
  2152. UINT r;
  2153. /* create an empty db */
  2154. hdb = create_db();
  2155. ok( hdb, "failed to create db\n");
  2156. memset(hviews, 0, sizeof(hviews));
  2157. for (i=0; i<MY_NVIEWS; i++) {
  2158. static char szQueryBuf[256] = "SELECT * from `_Tables`";
  2159. hviews[i] = 0xdeadbeeb;
  2160. r = MsiDatabaseOpenView(hdb, szQueryBuf, &hviews[i]);
  2161. if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb ||
  2162. hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
  2163. break;
  2164. }
  2165. ok( i == MY_NVIEWS, "problem opening views\n");
  2166. for (i=0; i<MY_NVIEWS; i++) {
  2167. if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
  2168. MsiViewClose(hviews[i]);
  2169. r = MsiCloseHandle(hviews[i]);
  2170. if (r != ERROR_SUCCESS)
  2171. break;
  2172. }
  2173. }
  2174. ok( i == MY_NVIEWS, "problem closing views\n");
  2175. r = MsiCloseHandle(hdb);
  2176. ok( r == ERROR_SUCCESS, "failed to close database\n");
  2177. }
  2178. static void generate_transform(void)
  2179. {
  2180. MSIHANDLE hdb1, hdb2, hrec;
  2181. LPCSTR query;
  2182. UINT r;
  2183. /* start with two identical databases */
  2184. CopyFile(msifile2, msifile, FALSE);
  2185. r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb1 );
  2186. ok( r == ERROR_SUCCESS , "Failed to create database\n" );
  2187. r = MsiDatabaseCommit( hdb1 );
  2188. ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
  2189. r = MsiOpenDatabase(msifile2, MSIDBOPEN_READONLY, &hdb2 );
  2190. ok( r == ERROR_SUCCESS , "Failed to create database\n" );
  2191. /* the transform between two identical database should be empty */
  2192. r = MsiDatabaseGenerateTransform(hdb1, hdb2, NULL, 0, 0);
  2193. todo_wine {
  2194. ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
  2195. }
  2196. query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
  2197. r = run_query(hdb1, 0, query);
  2198. ok(r == ERROR_SUCCESS, "failed to add table\n");
  2199. query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
  2200. r = run_query(hdb1, 0, query);
  2201. ok(r == ERROR_SUCCESS, "failed to add row 1\n");
  2202. query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
  2203. r = run_query(hdb1, 0, query);
  2204. ok(r == ERROR_SUCCESS, "failed to add row 2\n");
  2205. query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
  2206. r = run_query(hdb1, 0, query);
  2207. ok(r == ERROR_SUCCESS, "failed to modify row\n");
  2208. query = "DELETE FROM `MOO` WHERE `NOO` = 3";
  2209. r = run_query(hdb1, 0, query);
  2210. ok(r == ERROR_SUCCESS, "failed to delete row\n");
  2211. hrec = MsiCreateRecord(2);
  2212. r = MsiRecordSetInteger(hrec, 1, 1);
  2213. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  2214. write_file("testdata.bin", "naengmyon", 9);
  2215. r = MsiRecordSetStream(hrec, 2, "testdata.bin");
  2216. ok(r == ERROR_SUCCESS, "failed to set stream\n");
  2217. query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
  2218. r = run_query(hdb1, hrec, query);
  2219. ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
  2220. MsiCloseHandle(hrec);
  2221. query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
  2222. r = run_query(hdb1, 0, query);
  2223. ok(r == ERROR_SUCCESS, "failed to add column\n");
  2224. query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
  2225. r = run_query(hdb1, 0, query);
  2226. ok(r == ERROR_SUCCESS, "failed to add column\n");
  2227. query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
  2228. r = run_query(hdb1, 0, query);
  2229. ok(r == ERROR_SUCCESS, "failed to modify row\n");
  2230. query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
  2231. "`Value` CHAR(0) PRIMARY KEY `Property`)";
  2232. r = run_query(hdb1, 0, query);
  2233. ok(r == ERROR_SUCCESS, "failed to add property table\n");
  2234. query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
  2235. r = run_query(hdb1, 0, query);
  2236. ok(r == ERROR_SUCCESS, "failed to add property\n");
  2237. /* database needs to be committed */
  2238. MsiDatabaseCommit(hdb1);
  2239. r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
  2240. ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
  2241. MsiCloseHandle( hdb1 );
  2242. MsiCloseHandle( hdb2 );
  2243. DeleteFile("testdata.bin");
  2244. }
  2245. /* data for generating a transform */
  2246. /* tables transform names - encoded as they would be in an msi database file */
  2247. static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
  2248. static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
  2249. static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
  2250. static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
  2251. static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
  2252. static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
  2253. static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
  2254. static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
  2255. static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
  2256. /* data in each table */
  2257. static const WCHAR data1[] = { /* AAR */
  2258. 0x0201, 0x0008, 0x8001, /* 0x0201 = add row (1), two shorts */
  2259. 0x0201, 0x0009, 0x8002,
  2260. };
  2261. static const WCHAR data2[] = { /* _Columns */
  2262. 0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
  2263. 0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
  2264. 0x0401, 0x0005, 0x0000, 0x0006, 0xbdff, /* 0x0401 = add row (1), 4 shorts */
  2265. 0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
  2266. 0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
  2267. 0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
  2268. };
  2269. static const WCHAR data3[] = { /* _Tables */
  2270. 0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
  2271. 0x0101, 0x000a,
  2272. };
  2273. static const char data4[] = /* _StringData */
  2274. "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval"; /* all the strings squashed together */
  2275. static const WCHAR data5[] = { /* _StringPool */
  2276. /* len, refs */
  2277. 0, 0, /* string 0 '' */
  2278. 3, 2, /* string 1 'MOO' */
  2279. 3, 1, /* string 2 'COW' */
  2280. 3, 1, /* string 3 'PIG' */
  2281. 1, 1, /* string 4 'c' */
  2282. 3, 3, /* string 5 'AAR' */
  2283. 3, 1, /* string 6 'CAR' */
  2284. 3, 1, /* string 7 'BAR' */
  2285. 2, 1, /* string 8 'vw' */
  2286. 3, 1, /* string 9 'bmw' */
  2287. 8, 4, /* string 10 'Property' */
  2288. 5, 1, /* string 11 'Value' */
  2289. 4, 1, /* string 12 'prop' */
  2290. 3, 1, /* string 13 'val' */
  2291. };
  2292. /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
  2293. static const WCHAR data6[] = { /* MOO */
  2294. 0x000a, 0x8001, 0x0004, 0x8005, /* update row */
  2295. 0x0000, 0x8003, /* delete row */
  2296. };
  2297. static const WCHAR data7[] = { /* BINARY */
  2298. 0x0201, 0x8001, 0x0001,
  2299. };
  2300. static const char data8[] = /* stream data for the BINARY table */
  2301. "naengmyon";
  2302. static const WCHAR data9[] = { /* Property */
  2303. 0x0201, 0x000c, 0x000d,
  2304. };
  2305. static const struct {
  2306. LPCWSTR name;
  2307. const void *data;
  2308. DWORD size;
  2309. } table_transform_data[] =
  2310. {
  2311. { name1, data1, sizeof data1 },
  2312. { name2, data2, sizeof data2 },
  2313. { name3, data3, sizeof data3 },
  2314. { name4, data4, sizeof data4 - 1 },
  2315. { name5, data5, sizeof data5 },
  2316. { name6, data6, sizeof data6 },
  2317. { name7, data7, sizeof data7 },
  2318. { name8, data8, sizeof data8 - 1 },
  2319. { name9, data9, sizeof data9 },
  2320. };
  2321. #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
  2322. static void generate_transform_manual(void)
  2323. {
  2324. IStorage *stg = NULL;
  2325. IStream *stm;
  2326. WCHAR name[0x20];
  2327. HRESULT r;
  2328. DWORD i, count;
  2329. const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
  2330. const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
  2331. MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
  2332. r = StgCreateDocfile(name, mode, 0, &stg);
  2333. ok(r == S_OK, "failed to create storage\n");
  2334. if (!stg)
  2335. return;
  2336. r = IStorage_SetClass( stg, &CLSID_MsiTransform );
  2337. ok(r == S_OK, "failed to set storage type\n");
  2338. for (i=0; i<NUM_TRANSFORM_TABLES; i++)
  2339. {
  2340. r = IStorage_CreateStream( stg, table_transform_data[i].name,
  2341. STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
  2342. if (FAILED(r))
  2343. {
  2344. ok(0, "failed to create stream %08x\n", r);
  2345. continue;
  2346. }
  2347. r = IStream_Write( stm, table_transform_data[i].data,
  2348. table_transform_data[i].size, &count );
  2349. if (FAILED(r) || count != table_transform_data[i].size)
  2350. ok(0, "failed to write stream\n");
  2351. IStream_Release(stm);
  2352. }
  2353. IStorage_Release(stg);
  2354. }
  2355. static UINT set_summary_info(MSIHANDLE hdb)
  2356. {
  2357. UINT res;
  2358. MSIHANDLE suminfo;
  2359. /* build summary info */
  2360. res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
  2361. ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
  2362. res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
  2363. "Installation Database");
  2364. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2365. res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
  2366. "Installation Database");
  2367. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2368. res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
  2369. "Wine Hackers");
  2370. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2371. res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
  2372. ";1033,2057");
  2373. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2374. res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
  2375. "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
  2376. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2377. res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
  2378. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2379. res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
  2380. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2381. res = MsiSummaryInfoPersist(suminfo);
  2382. ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
  2383. res = MsiCloseHandle( suminfo);
  2384. ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
  2385. return res;
  2386. }
  2387. static MSIHANDLE create_package_db(LPCSTR filename)
  2388. {
  2389. MSIHANDLE hdb = 0;
  2390. UINT res;
  2391. DeleteFile(msifile);
  2392. /* create an empty database */
  2393. res = MsiOpenDatabase(filename, MSIDBOPEN_CREATE, &hdb );
  2394. ok( res == ERROR_SUCCESS , "Failed to create database\n" );
  2395. if( res != ERROR_SUCCESS )
  2396. return hdb;
  2397. res = MsiDatabaseCommit( hdb );
  2398. ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
  2399. res = set_summary_info(hdb);
  2400. ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
  2401. res = create_directory_table(hdb);
  2402. ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
  2403. return hdb;
  2404. }
  2405. static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
  2406. {
  2407. UINT res;
  2408. CHAR szPackage[12];
  2409. MSIHANDLE hPackage;
  2410. sprintf(szPackage, "#%u", hdb);
  2411. res = MsiOpenPackage(szPackage, &hPackage);
  2412. if (res != ERROR_SUCCESS)
  2413. return res;
  2414. res = MsiCloseHandle(hdb);
  2415. if (res != ERROR_SUCCESS)
  2416. {
  2417. MsiCloseHandle(hPackage);
  2418. return res;
  2419. }
  2420. *handle = hPackage;
  2421. return ERROR_SUCCESS;
  2422. }
  2423. static void test_try_transform(void)
  2424. {
  2425. MSIHANDLE hdb, hview, hrec, hpkg = 0;
  2426. LPCSTR query;
  2427. UINT r;
  2428. DWORD sz;
  2429. char buffer[MAX_PATH];
  2430. DeleteFile(msifile);
  2431. DeleteFile(mstfile);
  2432. /* create the database */
  2433. hdb = create_package_db(msifile);
  2434. ok(hdb, "Failed to create package db\n");
  2435. query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
  2436. r = run_query(hdb, 0, query);
  2437. ok(r == ERROR_SUCCESS, "failed to add table\n");
  2438. query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
  2439. r = run_query(hdb, 0, query);
  2440. ok(r == ERROR_SUCCESS, "failed to add row\n");
  2441. query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
  2442. r = run_query(hdb, 0, query);
  2443. ok(r == ERROR_SUCCESS, "failed to add row\n");
  2444. query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
  2445. r = run_query(hdb, 0, query);
  2446. ok(r == ERROR_SUCCESS, "failed to add row\n");
  2447. query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
  2448. r = run_query(hdb, 0, query);
  2449. ok(r == ERROR_SUCCESS, "failed to add table\n");
  2450. hrec = MsiCreateRecord(2);
  2451. r = MsiRecordSetInteger(hrec, 1, 2);
  2452. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  2453. write_file("testdata.bin", "lamyon", 6);
  2454. r = MsiRecordSetStream(hrec, 2, "testdata.bin");
  2455. ok(r == ERROR_SUCCESS, "failed to set stream\n");
  2456. query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
  2457. r = run_query(hdb, hrec, query);
  2458. ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
  2459. MsiCloseHandle(hrec);
  2460. r = MsiDatabaseCommit( hdb );
  2461. ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
  2462. MsiCloseHandle( hdb );
  2463. DeleteFileA("testdata.bin");
  2464. /*
  2465. * Both these generate an equivalent transform,
  2466. * but the first doesn't work in Wine yet
  2467. * because MsiDatabaseGenerateTransform is unimplemented.
  2468. */
  2469. if (0)
  2470. generate_transform();
  2471. else
  2472. generate_transform_manual();
  2473. r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb );
  2474. ok( r == ERROR_SUCCESS , "Failed to create database\n" );
  2475. r = MsiDatabaseApplyTransform( hdb, mstfile, 0 );
  2476. ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
  2477. MsiDatabaseCommit( hdb );
  2478. /* check new values */
  2479. hrec = 0;
  2480. query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
  2481. r = do_query(hdb, query, &hrec);
  2482. ok(r == ERROR_SUCCESS, "select query failed\n");
  2483. MsiCloseHandle(hrec);
  2484. query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
  2485. hrec = 0;
  2486. r = do_query(hdb, query, &hrec);
  2487. ok(r == ERROR_SUCCESS, "select query failed\n");
  2488. MsiCloseHandle(hrec);
  2489. /* check updated values */
  2490. hrec = 0;
  2491. query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
  2492. r = do_query(hdb, query, &hrec);
  2493. ok(r == ERROR_SUCCESS, "select query failed\n");
  2494. MsiCloseHandle(hrec);
  2495. /* check unchanged value */
  2496. hrec = 0;
  2497. query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
  2498. r = do_query(hdb, query, &hrec);
  2499. ok(r == ERROR_SUCCESS, "select query failed\n");
  2500. MsiCloseHandle(hrec);
  2501. /* check deleted value */
  2502. hrec = 0;
  2503. query = "select * from `MOO` where `NOO` = 3";
  2504. r = do_query(hdb, query, &hrec);
  2505. ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
  2506. if (hrec) MsiCloseHandle(hrec);
  2507. /* check added stream */
  2508. hrec = 0;
  2509. query = "select `BLOB` from `BINARY` where `ID` = 1";
  2510. r = do_query(hdb, query, &hrec);
  2511. ok(r == ERROR_SUCCESS, "select query failed\n");
  2512. /* check the contents of the stream */
  2513. sz = sizeof buffer;
  2514. r = MsiRecordReadStream( hrec, 1, buffer, &sz );
  2515. ok(r == ERROR_SUCCESS, "read stream failed\n");
  2516. ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
  2517. ok(sz == 9, "stream data was wrong size\n");
  2518. if (hrec) MsiCloseHandle(hrec);
  2519. /* check the validity of the table with a deleted row */
  2520. hrec = 0;
  2521. query = "select * from `MOO`";
  2522. r = MsiDatabaseOpenView(hdb, query, &hview);
  2523. ok(r == ERROR_SUCCESS, "open view failed\n");
  2524. r = MsiViewExecute(hview, 0);
  2525. ok(r == ERROR_SUCCESS, "view execute failed\n");
  2526. r = MsiViewFetch(hview, &hrec);
  2527. ok(r == ERROR_SUCCESS, "view fetch failed\n");
  2528. r = MsiRecordGetInteger(hrec, 1);
  2529. ok(r == 1, "Expected 1, got %d\n", r);
  2530. sz = sizeof buffer;
  2531. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  2532. ok(r == ERROR_SUCCESS, "record get string failed\n");
  2533. ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
  2534. r = MsiRecordGetInteger(hrec, 3);
  2535. ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
  2536. r = MsiRecordGetInteger(hrec, 4);
  2537. ok(r == 5, "Expected 5, got %d\n", r);
  2538. MsiCloseHandle(hrec);
  2539. r = MsiViewFetch(hview, &hrec);
  2540. ok(r == ERROR_SUCCESS, "view fetch failed\n");
  2541. r = MsiRecordGetInteger(hrec, 1);
  2542. ok(r == 2, "Expected 2, got %d\n", r);
  2543. sz = sizeof buffer;
  2544. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  2545. ok(r == ERROR_SUCCESS, "record get string failed\n");
  2546. ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
  2547. r = MsiRecordGetInteger(hrec, 3);
  2548. ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
  2549. r = MsiRecordGetInteger(hrec, 4);
  2550. ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
  2551. MsiCloseHandle(hrec);
  2552. r = MsiViewFetch(hview, &hrec);
  2553. ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
  2554. MsiCloseHandle(hrec);
  2555. MsiViewClose(hview);
  2556. MsiCloseHandle(hview);
  2557. /* check that the property was added */
  2558. r = package_from_db(hdb, &hpkg);
  2559. if (r == ERROR_INSTALL_PACKAGE_REJECTED)
  2560. {
  2561. skip("Not enough rights to perform tests\n");
  2562. goto error;
  2563. }
  2564. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
  2565. sz = MAX_PATH;
  2566. r = MsiGetProperty(hpkg, "prop", buffer, &sz);
  2567. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  2568. ok(!lstrcmp(buffer, "val"), "Expected val, got %s\n", buffer);
  2569. MsiCloseHandle(hpkg);
  2570. error:
  2571. MsiCloseHandle(hdb);
  2572. DeleteFile(msifile);
  2573. DeleteFile(mstfile);
  2574. }
  2575. struct join_res
  2576. {
  2577. const CHAR one[MAX_PATH];
  2578. const CHAR two[MAX_PATH];
  2579. };
  2580. struct join_res_4col
  2581. {
  2582. const CHAR one[MAX_PATH];
  2583. const CHAR two[MAX_PATH];
  2584. const CHAR three[MAX_PATH];
  2585. const CHAR four[MAX_PATH];
  2586. };
  2587. struct join_res_uint
  2588. {
  2589. UINT one;
  2590. UINT two;
  2591. UINT three;
  2592. UINT four;
  2593. UINT five;
  2594. UINT six;
  2595. };
  2596. static const struct join_res join_res_first[] =
  2597. {
  2598. { "alveolar", "procerus" },
  2599. { "septum", "procerus" },
  2600. { "septum", "nasalis" },
  2601. { "ramus", "nasalis" },
  2602. { "malar", "mentalis" },
  2603. };
  2604. static const struct join_res join_res_second[] =
  2605. {
  2606. { "nasal", "septum" },
  2607. { "mandible", "ramus" },
  2608. };
  2609. static const struct join_res join_res_third[] =
  2610. {
  2611. { "msvcp.dll", "abcdefgh" },
  2612. { "msvcr.dll", "ijklmnop" },
  2613. };
  2614. static const struct join_res join_res_fourth[] =
  2615. {
  2616. { "msvcp.dll.01234", "single.dll.31415" },
  2617. };
  2618. static const struct join_res join_res_fifth[] =
  2619. {
  2620. { "malar", "procerus" },
  2621. };
  2622. static const struct join_res join_res_sixth[] =
  2623. {
  2624. { "malar", "procerus" },
  2625. { "malar", "procerus" },
  2626. { "malar", "nasalis" },
  2627. { "malar", "nasalis" },
  2628. { "malar", "nasalis" },
  2629. { "malar", "mentalis" },
  2630. };
  2631. static const struct join_res join_res_seventh[] =
  2632. {
  2633. { "malar", "nasalis" },
  2634. { "malar", "nasalis" },
  2635. { "malar", "nasalis" },
  2636. };
  2637. static const struct join_res_4col join_res_eighth[] =
  2638. {
  2639. { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
  2640. { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
  2641. { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
  2642. { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
  2643. { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
  2644. { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
  2645. };
  2646. static const struct join_res_uint join_res_ninth[] =
  2647. {
  2648. { 1, 2, 3, 4, 7, 8 },
  2649. { 1, 2, 5, 6, 7, 8 },
  2650. { 1, 2, 3, 4, 9, 10 },
  2651. { 1, 2, 5, 6, 9, 10 },
  2652. { 1, 2, 3, 4, 11, 12 },
  2653. { 1, 2, 5, 6, 11, 12 },
  2654. };
  2655. static void test_join(void)
  2656. {
  2657. MSIHANDLE hdb, hview, hrec;
  2658. LPCSTR query;
  2659. CHAR buf[MAX_PATH];
  2660. UINT r, count;
  2661. DWORD size, i;
  2662. BOOL data_correct;
  2663. hdb = create_db();
  2664. ok( hdb, "failed to create db\n");
  2665. r = create_component_table( hdb );
  2666. ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
  2667. r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
  2668. ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
  2669. r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
  2670. ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
  2671. r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
  2672. ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
  2673. r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
  2674. ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
  2675. r = create_feature_components_table( hdb );
  2676. ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
  2677. r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
  2678. ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
  2679. r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
  2680. ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
  2681. r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
  2682. ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
  2683. r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
  2684. ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
  2685. r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
  2686. ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
  2687. r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
  2688. ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
  2689. r = create_std_dlls_table( hdb );
  2690. ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
  2691. r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
  2692. ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
  2693. r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
  2694. ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
  2695. r = create_binary_table( hdb );
  2696. ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
  2697. r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
  2698. ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
  2699. r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
  2700. ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
  2701. r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
  2702. ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
  2703. query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
  2704. r = run_query( hdb, 0, query);
  2705. ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
  2706. query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
  2707. r = run_query( hdb, 0, query);
  2708. ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
  2709. query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
  2710. r = run_query( hdb, 0, query);
  2711. ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
  2712. query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
  2713. r = run_query( hdb, 0, query);
  2714. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2715. query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
  2716. r = run_query( hdb, 0, query);
  2717. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2718. query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
  2719. r = run_query( hdb, 0, query);
  2720. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2721. query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
  2722. r = run_query( hdb, 0, query);
  2723. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2724. query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
  2725. r = run_query( hdb, 0, query);
  2726. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2727. query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
  2728. r = run_query( hdb, 0, query);
  2729. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2730. query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
  2731. r = run_query( hdb, 0, query);
  2732. ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
  2733. query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
  2734. r = run_query( hdb, 0, query);
  2735. ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
  2736. query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
  2737. r = run_query( hdb, 0, query);
  2738. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2739. query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
  2740. r = run_query( hdb, 0, query);
  2741. ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
  2742. query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
  2743. "FROM `Component`, `FeatureComponents` "
  2744. "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
  2745. "ORDER BY `Feature_`";
  2746. r = MsiDatabaseOpenView(hdb, query, &hview);
  2747. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2748. r = MsiViewExecute(hview, 0);
  2749. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2750. i = 0;
  2751. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2752. {
  2753. count = MsiRecordGetFieldCount( hrec );
  2754. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2755. size = MAX_PATH;
  2756. r = MsiRecordGetString( hrec, 1, buf, &size );
  2757. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2758. ok( !lstrcmp( buf, join_res_first[i].one ),
  2759. "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
  2760. size = MAX_PATH;
  2761. r = MsiRecordGetString( hrec, 2, buf, &size );
  2762. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2763. ok( !lstrcmp( buf, join_res_first[i].two ),
  2764. "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
  2765. i++;
  2766. MsiCloseHandle(hrec);
  2767. }
  2768. ok( i == 5, "Expected 5 rows, got %d\n", i );
  2769. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2770. MsiViewClose(hview);
  2771. MsiCloseHandle(hview);
  2772. /* try a join without a WHERE condition */
  2773. query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
  2774. "FROM `Component`, `FeatureComponents` ";
  2775. r = MsiDatabaseOpenView(hdb, query, &hview);
  2776. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2777. r = MsiViewExecute(hview, 0);
  2778. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2779. i = 0;
  2780. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2781. {
  2782. i++;
  2783. MsiCloseHandle(hrec);
  2784. }
  2785. ok( i == 24, "Expected 24 rows, got %d\n", i );
  2786. MsiViewClose(hview);
  2787. MsiCloseHandle(hview);
  2788. query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
  2789. "WHERE FeatureComponents.Component_=Component.Component "
  2790. "AND (Feature_='nasalis') ORDER BY Feature_";
  2791. r = MsiDatabaseOpenView(hdb, query, &hview);
  2792. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2793. r = MsiViewExecute(hview, 0);
  2794. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2795. i = 0;
  2796. data_correct = TRUE;
  2797. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2798. {
  2799. count = MsiRecordGetFieldCount( hrec );
  2800. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2801. size = MAX_PATH;
  2802. r = MsiRecordGetString( hrec, 1, buf, &size );
  2803. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2804. if( lstrcmp( buf, join_res_second[i].one ))
  2805. data_correct = FALSE;
  2806. size = MAX_PATH;
  2807. r = MsiRecordGetString( hrec, 2, buf, &size );
  2808. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2809. if( lstrcmp( buf, join_res_second[i].two ))
  2810. data_correct = FALSE;
  2811. i++;
  2812. MsiCloseHandle(hrec);
  2813. }
  2814. ok( data_correct, "data returned in the wrong order\n");
  2815. ok( i == 2, "Expected 2 rows, got %d\n", i );
  2816. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2817. MsiViewClose(hview);
  2818. MsiCloseHandle(hview);
  2819. query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
  2820. "FROM `StdDlls`, `Binary` "
  2821. "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
  2822. "ORDER BY `File`";
  2823. r = MsiDatabaseOpenView(hdb, query, &hview);
  2824. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2825. r = MsiViewExecute(hview, 0);
  2826. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2827. i = 0;
  2828. data_correct = TRUE;
  2829. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2830. {
  2831. count = MsiRecordGetFieldCount( hrec );
  2832. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2833. size = MAX_PATH;
  2834. r = MsiRecordGetString( hrec, 1, buf, &size );
  2835. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2836. if( lstrcmp( buf, join_res_third[i].one ) )
  2837. data_correct = FALSE;
  2838. size = MAX_PATH;
  2839. r = MsiRecordGetString( hrec, 2, buf, &size );
  2840. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2841. if( lstrcmp( buf, join_res_third[i].two ) )
  2842. data_correct = FALSE;
  2843. i++;
  2844. MsiCloseHandle(hrec);
  2845. }
  2846. ok( data_correct, "data returned in the wrong order\n");
  2847. ok( i == 2, "Expected 2 rows, got %d\n", i );
  2848. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2849. MsiViewClose(hview);
  2850. MsiCloseHandle(hview);
  2851. query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
  2852. "FROM `StdDlls`, `Binary` "
  2853. "WHERE `StdDlls`.`File` = `Binary`.`Data` "
  2854. "ORDER BY `Name`";
  2855. r = MsiDatabaseOpenView(hdb, query, &hview);
  2856. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2857. r = MsiViewExecute(hview, 0);
  2858. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2859. i = 0;
  2860. data_correct = TRUE;
  2861. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2862. {
  2863. count = MsiRecordGetFieldCount( hrec );
  2864. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2865. size = MAX_PATH;
  2866. r = MsiRecordGetString( hrec, 1, buf, &size );
  2867. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2868. if( lstrcmp( buf, join_res_fourth[i].one ))
  2869. data_correct = FALSE;
  2870. size = MAX_PATH;
  2871. r = MsiRecordGetString( hrec, 2, buf, &size );
  2872. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2873. if( lstrcmp( buf, join_res_fourth[i].two ))
  2874. data_correct = FALSE;
  2875. i++;
  2876. MsiCloseHandle(hrec);
  2877. }
  2878. ok( data_correct, "data returned in the wrong order\n");
  2879. ok( i == 1, "Expected 1 rows, got %d\n", i );
  2880. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2881. MsiViewClose(hview);
  2882. MsiCloseHandle(hview);
  2883. query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
  2884. "FROM `Component`, `FeatureComponents` "
  2885. "WHERE `Component`.`Component` = 'zygomatic' "
  2886. "AND `FeatureComponents`.`Component_` = 'maxilla' "
  2887. "ORDER BY `Feature_`";
  2888. r = MsiDatabaseOpenView(hdb, query, &hview);
  2889. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2890. r = MsiViewExecute(hview, 0);
  2891. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2892. i = 0;
  2893. data_correct = TRUE;
  2894. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2895. {
  2896. count = MsiRecordGetFieldCount( hrec );
  2897. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2898. size = MAX_PATH;
  2899. r = MsiRecordGetString( hrec, 1, buf, &size );
  2900. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2901. if( lstrcmp( buf, join_res_fifth[i].one ))
  2902. data_correct = FALSE;
  2903. size = MAX_PATH;
  2904. r = MsiRecordGetString( hrec, 2, buf, &size );
  2905. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2906. if( lstrcmp( buf, join_res_fifth[i].two ))
  2907. data_correct = FALSE;
  2908. i++;
  2909. MsiCloseHandle(hrec);
  2910. }
  2911. ok( data_correct, "data returned in the wrong order\n");
  2912. ok( i == 1, "Expected 1 rows, got %d\n", i );
  2913. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2914. MsiViewClose(hview);
  2915. MsiCloseHandle(hview);
  2916. query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
  2917. "FROM `Component`, `FeatureComponents` "
  2918. "WHERE `Component` = 'zygomatic' "
  2919. "ORDER BY `Feature_`";
  2920. r = MsiDatabaseOpenView(hdb, query, &hview);
  2921. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2922. r = MsiViewExecute(hview, 0);
  2923. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2924. i = 0;
  2925. data_correct = TRUE;
  2926. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2927. {
  2928. count = MsiRecordGetFieldCount( hrec );
  2929. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2930. size = MAX_PATH;
  2931. r = MsiRecordGetString( hrec, 1, buf, &size );
  2932. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2933. if( lstrcmp( buf, join_res_sixth[i].one ))
  2934. data_correct = FALSE;
  2935. size = MAX_PATH;
  2936. r = MsiRecordGetString( hrec, 2, buf, &size );
  2937. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2938. if( lstrcmp( buf, join_res_sixth[i].two ))
  2939. data_correct = FALSE;
  2940. i++;
  2941. MsiCloseHandle(hrec);
  2942. }
  2943. ok( data_correct, "data returned in the wrong order\n");
  2944. ok( i == 6, "Expected 6 rows, got %d\n", i );
  2945. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2946. MsiViewClose(hview);
  2947. MsiCloseHandle(hview);
  2948. query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
  2949. "FROM `Component`, `FeatureComponents` "
  2950. "WHERE `Component` = 'zygomatic' "
  2951. "AND `Feature_` = 'nasalis' "
  2952. "ORDER BY `Feature_`";
  2953. r = MsiDatabaseOpenView(hdb, query, &hview);
  2954. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2955. r = MsiViewExecute(hview, 0);
  2956. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2957. i = 0;
  2958. data_correct = TRUE;
  2959. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2960. {
  2961. count = MsiRecordGetFieldCount( hrec );
  2962. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2963. size = MAX_PATH;
  2964. r = MsiRecordGetString( hrec, 1, buf, &size );
  2965. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2966. if( lstrcmp( buf, join_res_seventh[i].one ))
  2967. data_correct = FALSE;
  2968. size = MAX_PATH;
  2969. r = MsiRecordGetString( hrec, 2, buf, &size );
  2970. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2971. if( lstrcmp( buf, join_res_seventh[i].two ))
  2972. data_correct = FALSE;
  2973. i++;
  2974. MsiCloseHandle(hrec);
  2975. }
  2976. ok( data_correct, "data returned in the wrong order\n");
  2977. ok( i == 3, "Expected 3 rows, got %d\n", i );
  2978. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  2979. MsiViewClose(hview);
  2980. MsiCloseHandle(hview);
  2981. query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
  2982. "FROM `StdDlls`, `Binary` ";
  2983. r = MsiDatabaseOpenView(hdb, query, &hview);
  2984. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  2985. r = MsiViewExecute(hview, 0);
  2986. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  2987. i = 0;
  2988. data_correct = TRUE;
  2989. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  2990. {
  2991. count = MsiRecordGetFieldCount( hrec );
  2992. ok( count == 2, "Expected 2 record fields, got %d\n", count );
  2993. size = MAX_PATH;
  2994. r = MsiRecordGetString( hrec, 1, buf, &size );
  2995. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  2996. if( lstrcmp( buf, join_res_eighth[i].one ))
  2997. data_correct = FALSE;
  2998. size = MAX_PATH;
  2999. r = MsiRecordGetString( hrec, 2, buf, &size );
  3000. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  3001. if( lstrcmp( buf, join_res_eighth[i].four ))
  3002. data_correct = FALSE;
  3003. i++;
  3004. MsiCloseHandle(hrec);
  3005. }
  3006. ok( data_correct, "data returned in the wrong order\n");
  3007. ok( i == 6, "Expected 6 rows, got %d\n", i );
  3008. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  3009. MsiViewClose(hview);
  3010. MsiCloseHandle(hview);
  3011. query = "SELECT * FROM `StdDlls`, `Binary` ";
  3012. r = MsiDatabaseOpenView(hdb, query, &hview);
  3013. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  3014. r = MsiViewExecute(hview, 0);
  3015. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  3016. i = 0;
  3017. data_correct = TRUE;
  3018. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  3019. {
  3020. count = MsiRecordGetFieldCount( hrec );
  3021. ok( count == 4, "Expected 4 record fields, got %d\n", count );
  3022. size = MAX_PATH;
  3023. r = MsiRecordGetString( hrec, 1, buf, &size );
  3024. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  3025. if( lstrcmp( buf, join_res_eighth[i].one ))
  3026. data_correct = FALSE;
  3027. size = MAX_PATH;
  3028. r = MsiRecordGetString( hrec, 2, buf, &size );
  3029. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  3030. if( lstrcmp( buf, join_res_eighth[i].two ))
  3031. data_correct = FALSE;
  3032. size = MAX_PATH;
  3033. r = MsiRecordGetString( hrec, 3, buf, &size );
  3034. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  3035. if( lstrcmp( buf, join_res_eighth[i].three ))
  3036. data_correct = FALSE;
  3037. size = MAX_PATH;
  3038. r = MsiRecordGetString( hrec, 4, buf, &size );
  3039. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  3040. if( lstrcmp( buf, join_res_eighth[i].four ))
  3041. data_correct = FALSE;
  3042. i++;
  3043. MsiCloseHandle(hrec);
  3044. }
  3045. ok( data_correct, "data returned in the wrong order\n");
  3046. ok( i == 6, "Expected 6 rows, got %d\n", i );
  3047. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  3048. MsiViewClose(hview);
  3049. MsiCloseHandle(hview);
  3050. query = "SELECT * FROM `One`, `Two`, `Three` ";
  3051. r = MsiDatabaseOpenView(hdb, query, &hview);
  3052. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  3053. r = MsiViewExecute(hview, 0);
  3054. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  3055. i = 0;
  3056. data_correct = TRUE;
  3057. while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
  3058. {
  3059. count = MsiRecordGetFieldCount( hrec );
  3060. ok( count == 6, "Expected 6 record fields, got %d\n", count );
  3061. r = MsiRecordGetInteger( hrec, 1 );
  3062. if( r != join_res_ninth[i].one )
  3063. data_correct = FALSE;
  3064. r = MsiRecordGetInteger( hrec, 2 );
  3065. if( r != join_res_ninth[i].two )
  3066. data_correct = FALSE;
  3067. r = MsiRecordGetInteger( hrec, 3 );
  3068. if( r != join_res_ninth[i].three )
  3069. data_correct = FALSE;
  3070. r = MsiRecordGetInteger( hrec, 4 );
  3071. if( r != join_res_ninth[i].four )
  3072. data_correct = FALSE;
  3073. r = MsiRecordGetInteger( hrec, 5 );
  3074. if( r != join_res_ninth[i].five )
  3075. data_correct = FALSE;
  3076. r = MsiRecordGetInteger( hrec, 6);
  3077. if( r != join_res_ninth[i].six )
  3078. data_correct = FALSE;
  3079. i++;
  3080. MsiCloseHandle(hrec);
  3081. }
  3082. ok( data_correct, "data returned in the wrong order\n");
  3083. ok( i == 6, "Expected 6 rows, got %d\n", i );
  3084. ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
  3085. MsiViewClose(hview);
  3086. MsiCloseHandle(hview);
  3087. query = "SELECT * FROM `Four`, `Five`";
  3088. r = MsiDatabaseOpenView(hdb, query, &hview);
  3089. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  3090. r = MsiViewExecute(hview, 0);
  3091. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  3092. r = MsiViewFetch(hview, &hrec);
  3093. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  3094. MsiViewClose(hview);
  3095. MsiCloseHandle(hview);
  3096. query = "SELECT * FROM `Nonexistent`, `One`";
  3097. r = MsiDatabaseOpenView(hdb, query, &hview);
  3098. ok( r == ERROR_BAD_QUERY_SYNTAX,
  3099. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
  3100. /* try updating a row in a join table */
  3101. query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
  3102. "FROM `Component`, `FeatureComponents` "
  3103. "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
  3104. "ORDER BY `Feature_`";
  3105. r = MsiDatabaseOpenView(hdb, query, &hview);
  3106. ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
  3107. r = MsiViewExecute(hview, 0);
  3108. ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
  3109. r = MsiViewFetch(hview, &hrec);
  3110. ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
  3111. r = MsiRecordSetString( hrec, 1, "epicranius" );
  3112. ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
  3113. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  3114. ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
  3115. /* try another valid operation for joins */
  3116. r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
  3117. todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
  3118. /* try an invalid operation for joins */
  3119. r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
  3120. ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
  3121. r = MsiRecordSetString( hrec, 2, "epicranius" );
  3122. ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
  3123. /* primary key cannot be updated */
  3124. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  3125. ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
  3126. MsiCloseHandle(hrec);
  3127. MsiViewClose(hview);
  3128. MsiCloseHandle(hview);
  3129. r = MsiDatabaseOpenView(hdb, query, &hview);
  3130. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  3131. r = MsiViewExecute(hview, 0);
  3132. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  3133. r = MsiViewFetch(hview, &hrec);
  3134. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3135. size = MAX_PATH;
  3136. r = MsiRecordGetString( hrec, 1, buf, &size );
  3137. ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
  3138. ok( !lstrcmp( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
  3139. MsiCloseHandle(hrec);
  3140. MsiViewClose(hview);
  3141. MsiCloseHandle(hview);
  3142. MsiCloseHandle(hdb);
  3143. DeleteFile(msifile);
  3144. }
  3145. static void test_temporary_table(void)
  3146. {
  3147. MSICONDITION cond;
  3148. MSIHANDLE hdb = 0, view = 0, rec;
  3149. const char *query;
  3150. UINT r;
  3151. char buf[0x10];
  3152. DWORD sz;
  3153. cond = MsiDatabaseIsTablePersistent(0, NULL);
  3154. ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
  3155. hdb = create_db();
  3156. ok( hdb, "failed to create db\n");
  3157. cond = MsiDatabaseIsTablePersistent(hdb, NULL);
  3158. ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
  3159. cond = MsiDatabaseIsTablePersistent(hdb, "_Tables");
  3160. ok( cond == MSICONDITION_NONE, "wrong return condition\n");
  3161. cond = MsiDatabaseIsTablePersistent(hdb, "_Columns");
  3162. ok( cond == MSICONDITION_NONE, "wrong return condition\n");
  3163. cond = MsiDatabaseIsTablePersistent(hdb, "_Storages");
  3164. ok( cond == MSICONDITION_NONE, "wrong return condition\n");
  3165. cond = MsiDatabaseIsTablePersistent(hdb, "_Streams");
  3166. ok( cond == MSICONDITION_NONE, "wrong return condition\n");
  3167. query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
  3168. r = run_query(hdb, 0, query);
  3169. ok(r == ERROR_SUCCESS, "failed to add table\n");
  3170. cond = MsiDatabaseIsTablePersistent(hdb, "P");
  3171. ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
  3172. query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
  3173. r = run_query(hdb, 0, query);
  3174. ok(r == ERROR_SUCCESS, "failed to add table\n");
  3175. cond = MsiDatabaseIsTablePersistent(hdb, "P2");
  3176. ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
  3177. query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
  3178. r = run_query(hdb, 0, query);
  3179. ok(r == ERROR_SUCCESS, "failed to add table\n");
  3180. cond = MsiDatabaseIsTablePersistent(hdb, "T");
  3181. ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
  3182. query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
  3183. r = run_query(hdb, 0, query);
  3184. ok(r == ERROR_SUCCESS, "failed to add table\n");
  3185. query = "SELECT * FROM `T2`";
  3186. r = MsiDatabaseOpenView(hdb, query, &view);
  3187. ok(r == ERROR_BAD_QUERY_SYNTAX,
  3188. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3189. cond = MsiDatabaseIsTablePersistent(hdb, "T2");
  3190. ok( cond == MSICONDITION_NONE, "wrong return condition\n");
  3191. query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
  3192. r = run_query(hdb, 0, query);
  3193. ok(r == ERROR_SUCCESS, "failed to add table\n");
  3194. cond = MsiDatabaseIsTablePersistent(hdb, "T3");
  3195. ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
  3196. query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
  3197. r = run_query(hdb, 0, query);
  3198. ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
  3199. cond = MsiDatabaseIsTablePersistent(hdb, "T4");
  3200. ok( cond == MSICONDITION_NONE, "wrong return condition\n");
  3201. query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
  3202. r = run_query(hdb, 0, query);
  3203. ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
  3204. query = "select * from `T`";
  3205. r = MsiDatabaseOpenView(hdb, query, &view);
  3206. ok(r == ERROR_SUCCESS, "failed to query table\n");
  3207. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  3208. ok(r == ERROR_SUCCESS, "failed to get column info\n");
  3209. sz = sizeof buf;
  3210. r = MsiRecordGetString(rec, 1, buf, &sz);
  3211. ok(r == ERROR_SUCCESS, "failed to get string\n");
  3212. ok( 0 == strcmp("G255", buf), "wrong column type\n");
  3213. sz = sizeof buf;
  3214. r = MsiRecordGetString(rec, 2, buf, &sz);
  3215. ok(r == ERROR_SUCCESS, "failed to get string\n");
  3216. ok( 0 == strcmp("j2", buf), "wrong column type\n");
  3217. MsiCloseHandle( rec );
  3218. MsiViewClose( view );
  3219. MsiCloseHandle( view );
  3220. /* query the table data */
  3221. rec = 0;
  3222. r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
  3223. ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
  3224. MsiCloseHandle( rec );
  3225. /* query the column data */
  3226. rec = 0;
  3227. r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
  3228. ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
  3229. if (rec) MsiCloseHandle( rec );
  3230. r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
  3231. ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
  3232. if (rec) MsiCloseHandle( rec );
  3233. MsiCloseHandle( hdb );
  3234. DeleteFile(msifile);
  3235. }
  3236. static void test_alter(void)
  3237. {
  3238. MSICONDITION cond;
  3239. MSIHANDLE hdb = 0;
  3240. const char *query;
  3241. UINT r;
  3242. hdb = create_db();
  3243. ok( hdb, "failed to create db\n");
  3244. query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
  3245. r = run_query(hdb, 0, query);
  3246. ok(r == ERROR_SUCCESS, "failed to add table\n");
  3247. cond = MsiDatabaseIsTablePersistent(hdb, "T");
  3248. ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
  3249. query = "ALTER TABLE `T` HOLD";
  3250. r = run_query(hdb, 0, query);
  3251. ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
  3252. query = "ALTER TABLE `T` FREE";
  3253. r = run_query(hdb, 0, query);
  3254. ok(r == ERROR_SUCCESS, "failed to free table\n");
  3255. query = "ALTER TABLE `T` FREE";
  3256. r = run_query(hdb, 0, query);
  3257. ok(r == ERROR_SUCCESS, "failed to free table\n");
  3258. query = "ALTER TABLE `T` FREE";
  3259. r = run_query(hdb, 0, query);
  3260. ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
  3261. query = "ALTER TABLE `T` HOLD";
  3262. r = run_query(hdb, 0, query);
  3263. ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
  3264. /* table T is removed */
  3265. query = "SELECT * FROM `T`";
  3266. r = run_query(hdb, 0, query);
  3267. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3268. /* create the table again */
  3269. query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
  3270. r = run_query(hdb, 0, query);
  3271. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3272. /* up the ref count */
  3273. query = "ALTER TABLE `U` HOLD";
  3274. r = run_query(hdb, 0, query);
  3275. ok(r == ERROR_SUCCESS, "failed to free table\n");
  3276. /* add column, no data type */
  3277. query = "ALTER TABLE `U` ADD `C`";
  3278. r = run_query(hdb, 0, query);
  3279. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3280. query = "ALTER TABLE `U` ADD `C` INTEGER";
  3281. r = run_query(hdb, 0, query);
  3282. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3283. /* add column C again */
  3284. query = "ALTER TABLE `U` ADD `C` INTEGER";
  3285. r = run_query(hdb, 0, query);
  3286. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3287. query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
  3288. r = run_query(hdb, 0, query);
  3289. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3290. query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
  3291. r = run_query(hdb, 0, query);
  3292. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3293. query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
  3294. r = run_query(hdb, 0, query);
  3295. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3296. query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
  3297. r = run_query(hdb, 0, query);
  3298. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3299. query = "SELECT * FROM `U` WHERE `D` = 8";
  3300. r = run_query(hdb, 0, query);
  3301. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3302. query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
  3303. r = run_query(hdb, 0, query);
  3304. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3305. query = "ALTER COLUMN `D` FREE";
  3306. r = run_query(hdb, 0, query);
  3307. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3308. /* drop the ref count */
  3309. query = "ALTER TABLE `U` FREE";
  3310. r = run_query(hdb, 0, query);
  3311. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3312. /* table is not empty */
  3313. query = "SELECT * FROM `U`";
  3314. r = run_query(hdb, 0, query);
  3315. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3316. /* column D is removed */
  3317. query = "SELECT * FROM `U` WHERE `D` = 8";
  3318. r = run_query(hdb, 0, query);
  3319. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3320. query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
  3321. r = run_query(hdb, 0, query);
  3322. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3323. /* add the column again */
  3324. query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
  3325. r = run_query(hdb, 0, query);
  3326. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3327. /* up the ref count */
  3328. query = "ALTER TABLE `U` HOLD";
  3329. r = run_query(hdb, 0, query);
  3330. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3331. query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
  3332. r = run_query(hdb, 0, query);
  3333. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3334. query = "SELECT * FROM `U` WHERE `E` = 16";
  3335. r = run_query(hdb, 0, query);
  3336. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3337. /* drop the ref count */
  3338. query = "ALTER TABLE `U` FREE";
  3339. r = run_query(hdb, 0, query);
  3340. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3341. query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
  3342. r = run_query(hdb, 0, query);
  3343. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3344. query = "SELECT * FROM `U` WHERE `E` = 20";
  3345. r = run_query(hdb, 0, query);
  3346. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3347. /* drop the ref count */
  3348. query = "ALTER TABLE `U` FREE";
  3349. r = run_query(hdb, 0, query);
  3350. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3351. /* table still exists */
  3352. query = "SELECT * FROM `U`";
  3353. r = run_query(hdb, 0, query);
  3354. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3355. /* col E is removed */
  3356. query = "SELECT * FROM `U` WHERE `E` = 20";
  3357. r = run_query(hdb, 0, query);
  3358. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3359. query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
  3360. r = run_query(hdb, 0, query);
  3361. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3362. /* drop the ref count once more */
  3363. query = "ALTER TABLE `U` FREE";
  3364. r = run_query(hdb, 0, query);
  3365. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3366. /* table still exists */
  3367. query = "SELECT * FROM `U`";
  3368. r = run_query(hdb, 0, query);
  3369. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3370. MsiCloseHandle( hdb );
  3371. DeleteFile(msifile);
  3372. }
  3373. static void test_integers(void)
  3374. {
  3375. MSIHANDLE hdb = 0, view = 0, rec = 0;
  3376. DWORD count, i;
  3377. const char *query;
  3378. UINT r;
  3379. /* just MsiOpenDatabase should not create a file */
  3380. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  3381. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  3382. /* create a table */
  3383. query = "CREATE TABLE `integers` ( "
  3384. "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
  3385. "`five` SHORT NOT NULL, `six` INT NOT NULL, "
  3386. "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
  3387. "PRIMARY KEY `one`)";
  3388. r = MsiDatabaseOpenView(hdb, query, &view);
  3389. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  3390. r = MsiViewExecute(view, 0);
  3391. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  3392. r = MsiViewClose(view);
  3393. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3394. r = MsiCloseHandle(view);
  3395. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3396. query = "SELECT * FROM `integers`";
  3397. r = MsiDatabaseOpenView(hdb, query, &view);
  3398. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3399. r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
  3400. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3401. count = MsiRecordGetFieldCount(rec);
  3402. ok(count == 8, "Expected 8, got %d\n", count);
  3403. ok(check_record(rec, 1, "one"), "Expected one\n");
  3404. ok(check_record(rec, 2, "two"), "Expected two\n");
  3405. ok(check_record(rec, 3, "three"), "Expected three\n");
  3406. ok(check_record(rec, 4, "four"), "Expected four\n");
  3407. ok(check_record(rec, 5, "five"), "Expected five\n");
  3408. ok(check_record(rec, 6, "six"), "Expected six\n");
  3409. ok(check_record(rec, 7, "seven"), "Expected seven\n");
  3410. ok(check_record(rec, 8, "eight"), "Expected eight\n");
  3411. MsiCloseHandle(rec);
  3412. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  3413. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3414. count = MsiRecordGetFieldCount(rec);
  3415. ok(count == 8, "Expected 8, got %d\n", count);
  3416. ok(check_record(rec, 1, "I2"), "Expected I2\n");
  3417. ok(check_record(rec, 2, "I2"), "Expected I2\n");
  3418. ok(check_record(rec, 3, "I2"), "Expected I2\n");
  3419. ok(check_record(rec, 4, "I4"), "Expected I4\n");
  3420. ok(check_record(rec, 5, "i2"), "Expected i2\n");
  3421. ok(check_record(rec, 6, "i2"), "Expected i2\n");
  3422. ok(check_record(rec, 7, "i2"), "Expected i2\n");
  3423. ok(check_record(rec, 8, "i4"), "Expected i4\n");
  3424. MsiCloseHandle(rec);
  3425. MsiViewClose(view);
  3426. MsiCloseHandle(view);
  3427. /* insert values into it, NULL where NOT NULL is specified */
  3428. query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
  3429. "VALUES('', '', '', '', '', '', '', '')";
  3430. r = MsiDatabaseOpenView(hdb, query, &view);
  3431. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3432. r = MsiViewExecute(view, 0);
  3433. ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  3434. MsiViewClose(view);
  3435. MsiCloseHandle(view);
  3436. query = "SELECT * FROM `integers`";
  3437. r = do_query(hdb, query, &rec);
  3438. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  3439. r = MsiRecordGetFieldCount(rec);
  3440. ok(r == -1, "record count wrong: %d\n", r);
  3441. MsiCloseHandle(rec);
  3442. /* insert legitimate values into it */
  3443. query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
  3444. "VALUES('', '2', '', '4', '5', '6', '7', '8')";
  3445. r = MsiDatabaseOpenView(hdb, query, &view);
  3446. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3447. r = MsiViewExecute(view, 0);
  3448. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3449. query = "SELECT * FROM `integers`";
  3450. r = do_query(hdb, query, &rec);
  3451. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3452. r = MsiRecordGetFieldCount(rec);
  3453. ok(r == 8, "record count wrong: %d\n", r);
  3454. i = MsiRecordGetInteger(rec, 1);
  3455. ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
  3456. i = MsiRecordGetInteger(rec, 3);
  3457. ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
  3458. i = MsiRecordGetInteger(rec, 2);
  3459. ok(i == 2, "Expected 2, got %d\n", i);
  3460. i = MsiRecordGetInteger(rec, 4);
  3461. ok(i == 4, "Expected 4, got %d\n", i);
  3462. i = MsiRecordGetInteger(rec, 5);
  3463. ok(i == 5, "Expected 5, got %d\n", i);
  3464. i = MsiRecordGetInteger(rec, 6);
  3465. ok(i == 6, "Expected 6, got %d\n", i);
  3466. i = MsiRecordGetInteger(rec, 7);
  3467. ok(i == 7, "Expected 7, got %d\n", i);
  3468. i = MsiRecordGetInteger(rec, 8);
  3469. ok(i == 8, "Expected 8, got %d\n", i);
  3470. MsiCloseHandle(rec);
  3471. MsiViewClose(view);
  3472. MsiCloseHandle(view);
  3473. r = MsiDatabaseCommit(hdb);
  3474. ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
  3475. r = MsiCloseHandle(hdb);
  3476. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3477. r = DeleteFile(msifile);
  3478. ok(r == TRUE, "file didn't exist after commit\n");
  3479. }
  3480. static void test_update(void)
  3481. {
  3482. MSIHANDLE hdb = 0, view = 0, rec = 0;
  3483. CHAR result[MAX_PATH];
  3484. const char *query;
  3485. DWORD size;
  3486. UINT r;
  3487. /* just MsiOpenDatabase should not create a file */
  3488. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  3489. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  3490. /* create the Control table */
  3491. query = "CREATE TABLE `Control` ( "
  3492. "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
  3493. "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
  3494. "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
  3495. "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
  3496. r = MsiDatabaseOpenView(hdb, query, &view);
  3497. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  3498. r = MsiViewExecute(view, 0);
  3499. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  3500. r = MsiViewClose(view);
  3501. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3502. r = MsiCloseHandle(view);
  3503. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3504. /* add a control */
  3505. query = "INSERT INTO `Control` ( "
  3506. "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
  3507. "`Property`, `Text`, `Control_Next`, `Help` )"
  3508. "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
  3509. r = MsiDatabaseOpenView(hdb, query, &view);
  3510. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3511. r = MsiViewExecute(view, 0);
  3512. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3513. r = MsiViewClose(view);
  3514. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3515. r = MsiCloseHandle(view);
  3516. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3517. /* add a second control */
  3518. query = "INSERT INTO `Control` ( "
  3519. "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
  3520. "`Property`, `Text`, `Control_Next`, `Help` )"
  3521. "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
  3522. r = MsiDatabaseOpenView(hdb, query, &view);
  3523. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3524. r = MsiViewExecute(view, 0);
  3525. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3526. r = MsiViewClose(view);
  3527. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3528. r = MsiCloseHandle(view);
  3529. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3530. /* add a third control */
  3531. query = "INSERT INTO `Control` ( "
  3532. "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
  3533. "`Property`, `Text`, `Control_Next`, `Help` )"
  3534. "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
  3535. r = MsiDatabaseOpenView(hdb, query, &view);
  3536. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3537. r = MsiViewExecute(view, 0);
  3538. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3539. r = MsiViewClose(view);
  3540. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3541. r = MsiCloseHandle(view);
  3542. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3543. /* bad table */
  3544. query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
  3545. r = MsiDatabaseOpenView(hdb, query, &view);
  3546. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3547. /* bad set column */
  3548. query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
  3549. r = MsiDatabaseOpenView(hdb, query, &view);
  3550. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3551. /* bad where condition */
  3552. query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
  3553. r = MsiDatabaseOpenView(hdb, query, &view);
  3554. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  3555. /* just the dialog_ specified */
  3556. query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
  3557. r = MsiDatabaseOpenView(hdb, query, &view);
  3558. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3559. r = MsiViewExecute(view, 0);
  3560. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3561. r = MsiViewClose(view);
  3562. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3563. r = MsiCloseHandle(view);
  3564. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3565. /* check the modified text */
  3566. query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
  3567. r = MsiDatabaseOpenView(hdb, query, &view);
  3568. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3569. r = MsiViewExecute(view, 0);
  3570. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3571. r = MsiViewFetch(view, &rec);
  3572. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3573. size = MAX_PATH;
  3574. r = MsiRecordGetString(rec, 1, result, &size);
  3575. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3576. ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
  3577. MsiCloseHandle(rec);
  3578. r = MsiViewFetch(view, &rec);
  3579. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3580. size = MAX_PATH;
  3581. r = MsiRecordGetString(rec, 1, result, &size);
  3582. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3583. ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
  3584. MsiCloseHandle(rec);
  3585. r = MsiViewFetch(view, &rec);
  3586. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  3587. r = MsiViewClose(view);
  3588. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3589. r = MsiCloseHandle(view);
  3590. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3591. /* dialog_ and control specified */
  3592. query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
  3593. r = MsiDatabaseOpenView(hdb, query, &view);
  3594. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3595. r = MsiViewExecute(view, 0);
  3596. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3597. r = MsiViewClose(view);
  3598. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3599. r = MsiCloseHandle(view);
  3600. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3601. /* check the modified text */
  3602. query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
  3603. r = MsiDatabaseOpenView(hdb, query, &view);
  3604. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3605. r = MsiViewExecute(view, 0);
  3606. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3607. r = MsiViewFetch(view, &rec);
  3608. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3609. size = MAX_PATH;
  3610. r = MsiRecordGetString(rec, 1, result, &size);
  3611. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3612. ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
  3613. MsiCloseHandle(rec);
  3614. r = MsiViewFetch(view, &rec);
  3615. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3616. size = MAX_PATH;
  3617. r = MsiRecordGetString(rec, 1, result, &size);
  3618. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3619. ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
  3620. MsiCloseHandle(rec);
  3621. r = MsiViewFetch(view, &rec);
  3622. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  3623. r = MsiViewClose(view);
  3624. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3625. r = MsiCloseHandle(view);
  3626. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3627. /* no where condition */
  3628. query = "UPDATE `Control` SET `Text` = 'this is text'";
  3629. r = MsiDatabaseOpenView(hdb, query, &view);
  3630. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3631. r = MsiViewExecute(view, 0);
  3632. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3633. r = MsiViewClose(view);
  3634. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3635. r = MsiCloseHandle(view);
  3636. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3637. /* check the modified text */
  3638. query = "SELECT `Text` FROM `Control`";
  3639. r = MsiDatabaseOpenView(hdb, query, &view);
  3640. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3641. r = MsiViewExecute(view, 0);
  3642. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3643. r = MsiViewFetch(view, &rec);
  3644. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3645. size = MAX_PATH;
  3646. r = MsiRecordGetString(rec, 1, result, &size);
  3647. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3648. ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
  3649. MsiCloseHandle(rec);
  3650. r = MsiViewFetch(view, &rec);
  3651. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3652. size = MAX_PATH;
  3653. r = MsiRecordGetString(rec, 1, result, &size);
  3654. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3655. ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
  3656. MsiCloseHandle(rec);
  3657. r = MsiViewFetch(view, &rec);
  3658. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3659. size = MAX_PATH;
  3660. r = MsiRecordGetString(rec, 1, result, &size);
  3661. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3662. ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
  3663. MsiCloseHandle(rec);
  3664. r = MsiViewFetch(view, &rec);
  3665. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  3666. r = MsiViewClose(view);
  3667. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3668. r = MsiCloseHandle(view);
  3669. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3670. query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
  3671. "`Orange` CHAR(72), `Pear` INT PRIMARY KEY `Banana`)";
  3672. r = run_query(hdb, 0, query);
  3673. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3674. query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
  3675. "VALUES('one', 'two', 3)";
  3676. r = run_query(hdb, 0, query);
  3677. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3678. query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
  3679. "VALUES('three', 'four', 5)";
  3680. r = run_query(hdb, 0, query);
  3681. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3682. query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
  3683. "VALUES('six', 'two', 7)";
  3684. r = run_query(hdb, 0, query);
  3685. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3686. rec = MsiCreateRecord(2);
  3687. MsiRecordSetInteger(rec, 1, 8);
  3688. MsiRecordSetString(rec, 2, "two");
  3689. query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
  3690. r = run_query(hdb, rec, query);
  3691. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3692. MsiCloseHandle(rec);
  3693. query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
  3694. r = MsiDatabaseOpenView(hdb, query, &view);
  3695. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3696. r = MsiViewExecute(view, 0);
  3697. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3698. r = MsiViewFetch(view, &rec);
  3699. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3700. r = MsiRecordGetInteger(rec, 1);
  3701. ok(r == 8, "Expected 8, got %d\n", r);
  3702. MsiCloseHandle(rec);
  3703. r = MsiViewFetch(view, &rec);
  3704. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3705. r = MsiRecordGetInteger(rec, 1);
  3706. ok(r == 8, "Expected 8, got %d\n", r);
  3707. MsiCloseHandle(rec);
  3708. r = MsiViewFetch(view, &rec);
  3709. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3710. r = MsiRecordGetInteger(rec, 1);
  3711. ok(r == 5, "Expected 5, got %d\n", r);
  3712. MsiCloseHandle(rec);
  3713. r = MsiViewFetch(view, &rec);
  3714. ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
  3715. MsiViewClose(view);
  3716. MsiCloseHandle(view);
  3717. r = MsiDatabaseCommit(hdb);
  3718. ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
  3719. r = MsiCloseHandle(hdb);
  3720. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3721. DeleteFile(msifile);
  3722. }
  3723. static void test_special_tables(void)
  3724. {
  3725. const char *query;
  3726. MSIHANDLE hdb = 0;
  3727. UINT r;
  3728. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  3729. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  3730. query = "CREATE TABLE `_Properties` ( "
  3731. "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
  3732. r = run_query(hdb, 0, query);
  3733. ok(r == ERROR_SUCCESS, "failed to create table\n");
  3734. query = "CREATE TABLE `_Storages` ( "
  3735. "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
  3736. r = run_query(hdb, 0, query);
  3737. ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
  3738. query = "CREATE TABLE `_Streams` ( "
  3739. "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
  3740. r = run_query(hdb, 0, query);
  3741. ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
  3742. query = "CREATE TABLE `_Tables` ( "
  3743. "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
  3744. r = run_query(hdb, 0, query);
  3745. ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
  3746. query = "CREATE TABLE `_Columns` ( "
  3747. "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
  3748. r = run_query(hdb, 0, query);
  3749. ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
  3750. r = MsiCloseHandle(hdb);
  3751. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3752. }
  3753. static void test_tables_order(void)
  3754. {
  3755. const char *query;
  3756. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  3757. UINT r;
  3758. char buffer[100];
  3759. DWORD sz;
  3760. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  3761. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  3762. query = "CREATE TABLE `foo` ( "
  3763. "`baz` INT NOT NULL PRIMARY KEY `baz`)";
  3764. r = run_query(hdb, 0, query);
  3765. ok(r == ERROR_SUCCESS, "failed to create table\n");
  3766. query = "CREATE TABLE `bar` ( "
  3767. "`foo` INT NOT NULL PRIMARY KEY `foo`)";
  3768. r = run_query(hdb, 0, query);
  3769. ok(r == ERROR_SUCCESS, "failed to create table\n");
  3770. query = "CREATE TABLE `baz` ( "
  3771. "`bar` INT NOT NULL, "
  3772. "`baz` INT NOT NULL, "
  3773. "`foo` INT NOT NULL PRIMARY KEY `bar`)";
  3774. r = run_query(hdb, 0, query);
  3775. ok(r == ERROR_SUCCESS, "failed to create table\n");
  3776. /* The names of the tables in the _Tables table must
  3777. be in the same order as these names are created in
  3778. the strings table. */
  3779. query = "SELECT * FROM `_Tables`";
  3780. r = MsiDatabaseOpenView(hdb, query, &hview);
  3781. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  3782. r = MsiViewExecute(hview, 0);
  3783. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  3784. r = MsiViewFetch(hview, &hrec);
  3785. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3786. sz = sizeof(buffer);
  3787. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3788. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3789. ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
  3790. r = MsiCloseHandle(hrec);
  3791. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3792. r = MsiViewFetch(hview, &hrec);
  3793. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3794. sz = sizeof(buffer);
  3795. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3796. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3797. ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
  3798. r = MsiCloseHandle(hrec);
  3799. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3800. r = MsiViewFetch(hview, &hrec);
  3801. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3802. sz = sizeof(buffer);
  3803. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3804. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3805. ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
  3806. r = MsiCloseHandle(hrec);
  3807. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3808. r = MsiViewClose(hview);
  3809. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3810. r = MsiCloseHandle(hview);
  3811. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3812. /* The names of the tables in the _Columns table must
  3813. be in the same order as these names are created in
  3814. the strings table. */
  3815. query = "SELECT * FROM `_Columns`";
  3816. r = MsiDatabaseOpenView(hdb, query, &hview);
  3817. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  3818. r = MsiViewExecute(hview, 0);
  3819. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  3820. r = MsiViewFetch(hview, &hrec);
  3821. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3822. sz = sizeof(buffer);
  3823. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3824. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3825. ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
  3826. sz = sizeof(buffer);
  3827. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  3828. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3829. ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
  3830. r = MsiCloseHandle(hrec);
  3831. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3832. r = MsiViewFetch(hview, &hrec);
  3833. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3834. sz = sizeof(buffer);
  3835. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3836. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3837. ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
  3838. sz = sizeof(buffer);
  3839. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  3840. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3841. ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
  3842. r = MsiCloseHandle(hrec);
  3843. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3844. r = MsiViewFetch(hview, &hrec);
  3845. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3846. sz = sizeof(buffer);
  3847. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3848. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3849. ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
  3850. sz = sizeof(buffer);
  3851. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  3852. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3853. ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
  3854. r = MsiCloseHandle(hrec);
  3855. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3856. r = MsiViewFetch(hview, &hrec);
  3857. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3858. sz = sizeof(buffer);
  3859. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3860. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3861. ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
  3862. sz = sizeof(buffer);
  3863. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  3864. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3865. ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
  3866. r = MsiCloseHandle(hrec);
  3867. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3868. r = MsiViewFetch(hview, &hrec);
  3869. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3870. sz = sizeof(buffer);
  3871. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3872. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3873. ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
  3874. sz = sizeof(buffer);
  3875. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  3876. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3877. ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
  3878. r = MsiCloseHandle(hrec);
  3879. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3880. r = MsiViewClose(hview);
  3881. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3882. r = MsiCloseHandle(hview);
  3883. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3884. r = MsiCloseHandle(hdb);
  3885. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3886. DeleteFile(msifile);
  3887. }
  3888. static void test_rows_order(void)
  3889. {
  3890. const char *query;
  3891. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  3892. UINT r;
  3893. char buffer[100];
  3894. DWORD sz;
  3895. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  3896. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  3897. query = "CREATE TABLE `foo` ( "
  3898. "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
  3899. r = run_query(hdb, 0, query);
  3900. ok(r == ERROR_SUCCESS, "failed to create table\n");
  3901. r = run_query(hdb, 0, "INSERT INTO `foo` "
  3902. "( `bar` ) VALUES ( 'A' )");
  3903. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3904. r = run_query(hdb, 0, "INSERT INTO `foo` "
  3905. "( `bar` ) VALUES ( 'B' )");
  3906. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3907. r = run_query(hdb, 0, "INSERT INTO `foo` "
  3908. "( `bar` ) VALUES ( 'C' )");
  3909. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3910. r = run_query(hdb, 0, "INSERT INTO `foo` "
  3911. "( `bar` ) VALUES ( 'D' )");
  3912. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3913. r = run_query(hdb, 0, "INSERT INTO `foo` "
  3914. "( `bar` ) VALUES ( 'E' )");
  3915. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3916. r = run_query(hdb, 0, "INSERT INTO `foo` "
  3917. "( `bar` ) VALUES ( 'F' )");
  3918. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3919. query = "CREATE TABLE `bar` ( "
  3920. "`foo` LONGCHAR NOT NULL, "
  3921. "`baz` LONGCHAR NOT NULL "
  3922. "PRIMARY KEY `foo` )";
  3923. r = run_query(hdb, 0, query);
  3924. ok(r == ERROR_SUCCESS, "failed to create table\n");
  3925. r = run_query(hdb, 0, "INSERT INTO `bar` "
  3926. "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
  3927. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3928. r = run_query(hdb, 0, "INSERT INTO `bar` "
  3929. "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
  3930. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3931. r = run_query(hdb, 0, "INSERT INTO `bar` "
  3932. "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
  3933. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3934. r = run_query(hdb, 0, "INSERT INTO `bar` "
  3935. "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
  3936. ok(r == ERROR_SUCCESS, "cannot add value to table\n");
  3937. /* The rows of the table must be ordered by the column values of
  3938. each row. For strings, the column value is the string id
  3939. in the string table. */
  3940. query = "SELECT * FROM `bar`";
  3941. r = MsiDatabaseOpenView(hdb, query, &hview);
  3942. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  3943. r = MsiViewExecute(hview, 0);
  3944. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  3945. r = MsiViewFetch(hview, &hrec);
  3946. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3947. sz = sizeof(buffer);
  3948. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3949. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3950. ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
  3951. sz = sizeof(buffer);
  3952. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  3953. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3954. ok(!lstrcmp(buffer, "B"), "Expected B, got %s\n", buffer);
  3955. r = MsiCloseHandle(hrec);
  3956. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3957. r = MsiViewFetch(hview, &hrec);
  3958. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3959. sz = sizeof(buffer);
  3960. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3961. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3962. ok(!lstrcmp(buffer, "C"), "Expected E, got %s\n", buffer);
  3963. sz = sizeof(buffer);
  3964. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  3965. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3966. ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
  3967. r = MsiCloseHandle(hrec);
  3968. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3969. r = MsiViewFetch(hview, &hrec);
  3970. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3971. sz = sizeof(buffer);
  3972. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3973. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3974. ok(!lstrcmp(buffer, "D"), "Expected D, got %s\n", buffer);
  3975. sz = sizeof(buffer);
  3976. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  3977. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3978. ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
  3979. r = MsiCloseHandle(hrec);
  3980. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3981. r = MsiViewFetch(hview, &hrec);
  3982. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  3983. sz = sizeof(buffer);
  3984. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  3985. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3986. ok(!lstrcmp(buffer, "F"), "Expected F, got %s\n", buffer);
  3987. sz = sizeof(buffer);
  3988. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  3989. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  3990. ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
  3991. r = MsiCloseHandle(hrec);
  3992. ok(r == ERROR_SUCCESS, "failed to close record\n");
  3993. r = MsiViewClose(hview);
  3994. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  3995. r = MsiCloseHandle(hview);
  3996. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3997. r = MsiCloseHandle(hdb);
  3998. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  3999. DeleteFile(msifile);
  4000. }
  4001. static void test_collation(void)
  4002. {
  4003. static const WCHAR query1[] =
  4004. {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
  4005. '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
  4006. '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
  4007. static const WCHAR query2[] =
  4008. {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
  4009. '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
  4010. '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
  4011. static const WCHAR query3[] =
  4012. {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
  4013. '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
  4014. ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
  4015. 'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
  4016. static const WCHAR query4[] =
  4017. {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
  4018. '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
  4019. 'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
  4020. static const WCHAR query5[] =
  4021. {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
  4022. '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
  4023. 'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
  4024. static const WCHAR query6[] =
  4025. {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
  4026. ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
  4027. static const WCHAR letter_C[] = {'C',0};
  4028. static const WCHAR letter_D[] = {'D',0};
  4029. static const WCHAR letter_a_ring[] = {'a',0x30a,0};
  4030. static const WCHAR letter_a_with_ring[] = {0xe5,0};
  4031. const char *query;
  4032. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  4033. UINT r;
  4034. char buffer[100];
  4035. WCHAR bufferW[100];
  4036. DWORD sz;
  4037. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  4038. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  4039. query = "CREATE TABLE `bar` ( "
  4040. "`foo` LONGCHAR NOT NULL, "
  4041. "`baz` LONGCHAR NOT NULL "
  4042. "PRIMARY KEY `foo` )";
  4043. r = run_query(hdb, 0, query);
  4044. ok(r == ERROR_SUCCESS, "failed to create table\n");
  4045. r = run_query(hdb, 0, query);
  4046. ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
  4047. r = run_query(hdb, 0, "INSERT INTO `bar` "
  4048. "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
  4049. ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
  4050. r = run_query(hdb, 0, "INSERT INTO `bar` "
  4051. "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
  4052. ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
  4053. r = run_queryW(hdb, 0, query1);
  4054. ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
  4055. r = run_queryW(hdb, 0, query2);
  4056. ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
  4057. r = run_queryW(hdb, 0, query3);
  4058. ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
  4059. r = run_queryW(hdb, 0, query4);
  4060. ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
  4061. r = run_queryW(hdb, 0, query5);
  4062. ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
  4063. query = "SELECT * FROM `bar`";
  4064. r = MsiDatabaseOpenView(hdb, query, &hview);
  4065. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4066. r = MsiViewExecute(hview, 0);
  4067. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4068. r = MsiViewFetch(hview, &hrec);
  4069. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4070. sz = sizeof(buffer);
  4071. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  4072. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4073. ok(!lstrcmp(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
  4074. sz = sizeof(buffer);
  4075. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  4076. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4077. ok(!lstrcmp(buffer, "A"), "Expected A, got '%s'\n", buffer);
  4078. MsiCloseHandle(hrec);
  4079. r = MsiViewFetch(hview, &hrec);
  4080. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4081. sz = sizeof(buffer);
  4082. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  4083. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4084. ok(!lstrcmp(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
  4085. sz = sizeof(buffer);
  4086. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  4087. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4088. ok(!lstrcmp(buffer, "B"), "Expected B, got '%s'\n", buffer);
  4089. MsiCloseHandle(hrec);
  4090. r = MsiViewFetch(hview, &hrec);
  4091. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4092. sz = sizeof(bufferW) / sizeof(bufferW[0]);
  4093. r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
  4094. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4095. ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)),
  4096. "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
  4097. sz = sizeof(bufferW) / sizeof(bufferW[0]);
  4098. r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
  4099. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4100. ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
  4101. MsiCloseHandle(hrec);
  4102. r = MsiViewFetch(hview, &hrec);
  4103. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4104. sz = sizeof(bufferW) / sizeof(bufferW[0]);
  4105. r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
  4106. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4107. ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
  4108. "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
  4109. sz = sizeof(bufferW) / sizeof(bufferW[0]);
  4110. r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
  4111. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4112. ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
  4113. MsiCloseHandle(hrec);
  4114. r = MsiViewClose(hview);
  4115. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4116. r = MsiCloseHandle(hview);
  4117. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4118. r = MsiDatabaseOpenViewW(hdb, query6, &hview);
  4119. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4120. r = MsiViewExecute(hview, 0);
  4121. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4122. r = MsiViewFetch(hview, &hrec);
  4123. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4124. sz = sizeof(bufferW) / sizeof(bufferW[0]);
  4125. r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
  4126. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4127. ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
  4128. "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
  4129. sz = sizeof(bufferW) / sizeof(bufferW[0]);
  4130. r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
  4131. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4132. ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
  4133. MsiCloseHandle(hrec);
  4134. r = MsiViewFetch(hview, &hrec);
  4135. ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
  4136. r = MsiViewClose(hview);
  4137. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4138. r = MsiCloseHandle(hview);
  4139. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4140. r = MsiCloseHandle(hdb);
  4141. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4142. DeleteFile(msifile);
  4143. }
  4144. static void test_select_markers(void)
  4145. {
  4146. MSIHANDLE hdb = 0, rec, view, res;
  4147. LPCSTR query;
  4148. UINT r;
  4149. DWORD size;
  4150. CHAR buf[MAX_PATH];
  4151. hdb = create_db();
  4152. ok( hdb, "failed to create db\n");
  4153. r = run_query(hdb, 0,
  4154. "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
  4155. ok(r == S_OK, "cannot create table: %d\n", r);
  4156. r = run_query(hdb, 0, "INSERT INTO `Table` "
  4157. "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
  4158. ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
  4159. r = run_query(hdb, 0, "INSERT INTO `Table` "
  4160. "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
  4161. ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
  4162. r = run_query(hdb, 0, "INSERT INTO `Table` "
  4163. "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
  4164. ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
  4165. r = run_query(hdb, 0, "INSERT INTO `Table` "
  4166. "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
  4167. ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
  4168. rec = MsiCreateRecord(2);
  4169. MsiRecordSetString(rec, 1, "apple");
  4170. MsiRecordSetString(rec, 2, "two");
  4171. query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
  4172. r = MsiDatabaseOpenView(hdb, query, &view);
  4173. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4174. r = MsiViewExecute(view, rec);
  4175. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4176. r = MsiViewFetch(view, &res);
  4177. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4178. size = MAX_PATH;
  4179. r = MsiRecordGetString(res, 1, buf, &size);
  4180. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4181. ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
  4182. size = MAX_PATH;
  4183. r = MsiRecordGetString(res, 2, buf, &size);
  4184. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4185. ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
  4186. r = MsiRecordGetInteger(res, 3);
  4187. ok(r == 1, "Expected 1, got %d\n", r);
  4188. MsiCloseHandle(res);
  4189. r = MsiViewFetch(view, &res);
  4190. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4191. size = MAX_PATH;
  4192. r = MsiRecordGetString(res, 1, buf, &size);
  4193. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4194. ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
  4195. size = MAX_PATH;
  4196. r = MsiRecordGetString(res, 2, buf, &size);
  4197. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4198. ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
  4199. r = MsiRecordGetInteger(res, 3);
  4200. ok(r == 2, "Expected 2, got %d\n", r);
  4201. MsiCloseHandle(res);
  4202. r = MsiViewFetch(view, &res);
  4203. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4204. MsiCloseHandle(rec);
  4205. MsiViewClose(view);
  4206. MsiCloseHandle(view);
  4207. rec = MsiCreateRecord(2);
  4208. MsiRecordSetString(rec, 1, "one");
  4209. MsiRecordSetInteger(rec, 2, 1);
  4210. query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
  4211. r = MsiDatabaseOpenView(hdb, query, &view);
  4212. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4213. r = MsiViewExecute(view, rec);
  4214. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4215. r = MsiViewFetch(view, &res);
  4216. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4217. size = MAX_PATH;
  4218. r = MsiRecordGetString(res, 1, buf, &size);
  4219. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4220. ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
  4221. size = MAX_PATH;
  4222. r = MsiRecordGetString(res, 2, buf, &size);
  4223. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4224. ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
  4225. r = MsiRecordGetInteger(res, 3);
  4226. ok(r == 2, "Expected 2, got %d\n", r);
  4227. MsiCloseHandle(res);
  4228. r = MsiViewFetch(view, &res);
  4229. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4230. size = MAX_PATH;
  4231. r = MsiRecordGetString(res, 1, buf, &size);
  4232. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4233. ok(!lstrcmp(buf, "banana"), "Expected banana, got %s\n", buf);
  4234. size = MAX_PATH;
  4235. r = MsiRecordGetString(res, 2, buf, &size);
  4236. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4237. ok(!lstrcmp(buf, "three"), "Expected three, got %s\n", buf);
  4238. r = MsiRecordGetInteger(res, 3);
  4239. ok(r == 3, "Expected 3, got %d\n", r);
  4240. MsiCloseHandle(res);
  4241. r = MsiViewFetch(view, &res);
  4242. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4243. MsiCloseHandle(rec);
  4244. MsiViewClose(view);
  4245. MsiCloseHandle(view);
  4246. MsiCloseHandle(hdb);
  4247. DeleteFile(msifile);
  4248. }
  4249. static void test_viewmodify_update(void)
  4250. {
  4251. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  4252. UINT i, test_max, offset, count;
  4253. const char *query;
  4254. UINT r;
  4255. DeleteFile(msifile);
  4256. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  4257. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  4258. query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
  4259. r = run_query( hdb, 0, query );
  4260. ok(r == ERROR_SUCCESS, "query failed\n");
  4261. query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
  4262. r = run_query( hdb, 0, query );
  4263. ok(r == ERROR_SUCCESS, "query failed\n");
  4264. query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
  4265. r = run_query( hdb, 0, query );
  4266. ok(r == ERROR_SUCCESS, "query failed\n");
  4267. query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
  4268. r = run_query( hdb, 0, query );
  4269. ok(r == ERROR_SUCCESS, "query failed\n");
  4270. query = "SELECT `B` FROM `table`";
  4271. r = MsiDatabaseOpenView(hdb, query, &hview);
  4272. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4273. r = MsiViewExecute(hview, 0);
  4274. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4275. r = MsiViewFetch(hview, &hrec);
  4276. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4277. r = MsiRecordSetInteger(hrec, 1, 0);
  4278. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  4279. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  4280. ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
  4281. r = MsiCloseHandle(hrec);
  4282. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4283. r = MsiViewClose(hview);
  4284. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4285. r = MsiCloseHandle(hview);
  4286. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4287. query = "SELECT * FROM `table`";
  4288. r = MsiDatabaseOpenView(hdb, query, &hview);
  4289. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4290. r = MsiViewExecute(hview, 0);
  4291. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4292. r = MsiViewFetch(hview, &hrec);
  4293. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4294. r = MsiRecordGetInteger(hrec, 1);
  4295. ok(r == 1, "Expected 1, got %d\n", r);
  4296. r = MsiRecordGetInteger(hrec, 2);
  4297. ok(r == 0, "Expected 0, got %d\n", r);
  4298. r = MsiCloseHandle(hrec);
  4299. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4300. r = MsiViewFetch(hview, &hrec);
  4301. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4302. r = MsiRecordGetInteger(hrec, 1);
  4303. ok(r == 3, "Expected 3, got %d\n", r);
  4304. r = MsiRecordGetInteger(hrec, 2);
  4305. ok(r == 4, "Expected 4, got %d\n", r);
  4306. r = MsiCloseHandle(hrec);
  4307. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4308. r = MsiViewFetch(hview, &hrec);
  4309. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4310. r = MsiRecordGetInteger(hrec, 1);
  4311. ok(r == 5, "Expected 5, got %d\n", r);
  4312. r = MsiRecordGetInteger(hrec, 2);
  4313. ok(r == 6, "Expected 6, got %d\n", r);
  4314. r = MsiCloseHandle(hrec);
  4315. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4316. r = MsiViewFetch(hview, &hrec);
  4317. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4318. r = MsiViewClose(hview);
  4319. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4320. r = MsiCloseHandle(hview);
  4321. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4322. /* loop through all elements */
  4323. query = "SELECT `B` FROM `table`";
  4324. r = MsiDatabaseOpenView(hdb, query, &hview);
  4325. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4326. r = MsiViewExecute(hview, 0);
  4327. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4328. while (TRUE)
  4329. {
  4330. r = MsiViewFetch(hview, &hrec);
  4331. if (r != ERROR_SUCCESS)
  4332. break;
  4333. r = MsiRecordSetInteger(hrec, 1, 0);
  4334. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  4335. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  4336. ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
  4337. r = MsiCloseHandle(hrec);
  4338. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4339. }
  4340. r = MsiViewClose(hview);
  4341. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4342. r = MsiCloseHandle(hview);
  4343. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4344. query = "SELECT * FROM `table`";
  4345. r = MsiDatabaseOpenView(hdb, query, &hview);
  4346. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4347. r = MsiViewExecute(hview, 0);
  4348. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4349. r = MsiViewFetch(hview, &hrec);
  4350. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4351. r = MsiRecordGetInteger(hrec, 1);
  4352. ok(r == 1, "Expected 1, got %d\n", r);
  4353. r = MsiRecordGetInteger(hrec, 2);
  4354. ok(r == 0, "Expected 0, got %d\n", r);
  4355. r = MsiCloseHandle(hrec);
  4356. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4357. r = MsiViewFetch(hview, &hrec);
  4358. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4359. r = MsiRecordGetInteger(hrec, 1);
  4360. ok(r == 3, "Expected 3, got %d\n", r);
  4361. r = MsiRecordGetInteger(hrec, 2);
  4362. ok(r == 0, "Expected 0, got %d\n", r);
  4363. r = MsiCloseHandle(hrec);
  4364. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4365. r = MsiViewFetch(hview, &hrec);
  4366. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4367. r = MsiRecordGetInteger(hrec, 1);
  4368. ok(r == 5, "Expected 5, got %d\n", r);
  4369. r = MsiRecordGetInteger(hrec, 2);
  4370. ok(r == 0, "Expected 0, got %d\n", r);
  4371. r = MsiCloseHandle(hrec);
  4372. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4373. r = MsiViewFetch(hview, &hrec);
  4374. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4375. r = MsiViewClose(hview);
  4376. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4377. r = MsiCloseHandle(hview);
  4378. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4379. query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
  4380. r = run_query( hdb, 0, query );
  4381. ok(r == ERROR_SUCCESS, "query failed\n");
  4382. query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
  4383. r = MsiDatabaseOpenView( hdb, query, &hview );
  4384. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4385. test_max = 100;
  4386. offset = 1234;
  4387. for(i = 0; i < test_max; i++)
  4388. {
  4389. hrec = MsiCreateRecord( 2 );
  4390. MsiRecordSetInteger( hrec, 1, test_max - i );
  4391. MsiRecordSetInteger( hrec, 2, i );
  4392. r = MsiViewExecute( hview, hrec );
  4393. ok(r == ERROR_SUCCESS, "Got %d\n", r);
  4394. r = MsiCloseHandle( hrec );
  4395. ok(r == ERROR_SUCCESS, "Got %d\n", r);
  4396. }
  4397. r = MsiViewClose( hview );
  4398. ok(r == ERROR_SUCCESS, "Got %d\n", r);
  4399. r = MsiCloseHandle( hview );
  4400. ok(r == ERROR_SUCCESS, "Got %d\n", r);
  4401. /* Update. */
  4402. query = "SELECT * FROM `table2` ORDER BY `B`";
  4403. r = MsiDatabaseOpenView( hdb, query, &hview);
  4404. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4405. r = MsiViewExecute( hview, 0 );
  4406. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4407. count = 0;
  4408. while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
  4409. {
  4410. UINT b = MsiRecordGetInteger( hrec, 2 );
  4411. r = MsiRecordSetInteger( hrec, 2, b + offset);
  4412. ok(r == ERROR_SUCCESS, "Got %d\n", r);
  4413. r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
  4414. ok(r == ERROR_SUCCESS, "Got %d\n", r);
  4415. r = MsiCloseHandle(hrec);
  4416. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4417. count++;
  4418. }
  4419. ok(count == test_max, "Got count %d\n", count);
  4420. r = MsiViewClose(hview);
  4421. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4422. r = MsiCloseHandle(hview);
  4423. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4424. /* Recheck. */
  4425. query = "SELECT * FROM `table2` ORDER BY `B`";
  4426. r = MsiDatabaseOpenView( hdb, query, &hview);
  4427. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4428. r = MsiViewExecute( hview, 0 );
  4429. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4430. count = 0;
  4431. while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
  4432. {
  4433. UINT a = MsiRecordGetInteger( hrec, 1 );
  4434. UINT b = MsiRecordGetInteger( hrec, 2 );
  4435. ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
  4436. a, b, test_max - a + offset, b);
  4437. r = MsiCloseHandle(hrec);
  4438. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4439. count++;
  4440. }
  4441. ok(count == test_max, "Got count %d\n", count);
  4442. r = MsiViewClose(hview);
  4443. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4444. r = MsiCloseHandle(hview);
  4445. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4446. r = MsiCloseHandle( hdb );
  4447. ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
  4448. }
  4449. static void test_viewmodify_assign(void)
  4450. {
  4451. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  4452. const char *query;
  4453. UINT r;
  4454. /* setup database */
  4455. DeleteFile(msifile);
  4456. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  4457. ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
  4458. query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
  4459. r = run_query( hdb, 0, query );
  4460. ok(r == ERROR_SUCCESS, "query failed\n");
  4461. /* assign to view, new primary key */
  4462. query = "SELECT * FROM `table`";
  4463. r = MsiDatabaseOpenView(hdb, query, &hview);
  4464. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4465. r = MsiViewExecute(hview, 0);
  4466. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4467. hrec = MsiCreateRecord(2);
  4468. ok(hrec != 0, "MsiCreateRecord failed\n");
  4469. r = MsiRecordSetInteger(hrec, 1, 1);
  4470. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  4471. r = MsiRecordSetInteger(hrec, 2, 2);
  4472. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  4473. r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
  4474. ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
  4475. r = MsiCloseHandle(hrec);
  4476. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4477. r = MsiViewClose(hview);
  4478. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4479. r = MsiCloseHandle(hview);
  4480. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4481. query = "SELECT * FROM `table`";
  4482. r = MsiDatabaseOpenView(hdb, query, &hview);
  4483. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4484. r = MsiViewExecute(hview, 0);
  4485. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4486. r = MsiViewFetch(hview, &hrec);
  4487. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4488. r = MsiRecordGetInteger(hrec, 1);
  4489. ok(r == 1, "Expected 1, got %d\n", r);
  4490. r = MsiRecordGetInteger(hrec, 2);
  4491. ok(r == 2, "Expected 2, got %d\n", r);
  4492. r = MsiCloseHandle(hrec);
  4493. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4494. r = MsiViewFetch(hview, &hrec);
  4495. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4496. r = MsiViewClose(hview);
  4497. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4498. r = MsiCloseHandle(hview);
  4499. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4500. /* assign to view, primary key matches */
  4501. query = "SELECT * FROM `table`";
  4502. r = MsiDatabaseOpenView(hdb, query, &hview);
  4503. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4504. r = MsiViewExecute(hview, 0);
  4505. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4506. hrec = MsiCreateRecord(2);
  4507. ok(hrec != 0, "MsiCreateRecord failed\n");
  4508. r = MsiRecordSetInteger(hrec, 1, 1);
  4509. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  4510. r = MsiRecordSetInteger(hrec, 2, 4);
  4511. ok(r == ERROR_SUCCESS, "failed to set integer\n");
  4512. r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
  4513. ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
  4514. r = MsiCloseHandle(hrec);
  4515. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4516. r = MsiViewClose(hview);
  4517. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4518. r = MsiCloseHandle(hview);
  4519. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4520. query = "SELECT * FROM `table`";
  4521. r = MsiDatabaseOpenView(hdb, query, &hview);
  4522. ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
  4523. r = MsiViewExecute(hview, 0);
  4524. ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
  4525. r = MsiViewFetch(hview, &hrec);
  4526. ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
  4527. r = MsiRecordGetInteger(hrec, 1);
  4528. ok(r == 1, "Expected 1, got %d\n", r);
  4529. r = MsiRecordGetInteger(hrec, 2);
  4530. ok(r == 4, "Expected 4, got %d\n", r);
  4531. r = MsiCloseHandle(hrec);
  4532. ok(r == ERROR_SUCCESS, "failed to close record\n");
  4533. r = MsiViewFetch(hview, &hrec);
  4534. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4535. r = MsiViewClose(hview);
  4536. ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
  4537. r = MsiCloseHandle(hview);
  4538. ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
  4539. /* close database */
  4540. r = MsiCloseHandle( hdb );
  4541. ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
  4542. }
  4543. static const WCHAR data10[] = { /* MOO */
  4544. 0x8001, 0x000b,
  4545. };
  4546. static const WCHAR data11[] = { /* AAR */
  4547. 0x8002, 0x8005,
  4548. 0x000c, 0x000f,
  4549. };
  4550. static const char data12[] = /* _StringData */
  4551. "MOOABAARCDonetwofourfive";
  4552. static const WCHAR data13[] = { /* _StringPool */
  4553. /* len, refs */
  4554. 0, 0, /* string 0 '' */
  4555. 0, 0, /* string 1 '' */
  4556. 0, 0, /* string 2 '' */
  4557. 0, 0, /* string 3 '' */
  4558. 0, 0, /* string 4 '' */
  4559. 3, 3, /* string 5 'MOO' */
  4560. 1, 1, /* string 6 'A' */
  4561. 1, 1, /* string 7 'B' */
  4562. 3, 3, /* string 8 'AAR' */
  4563. 1, 1, /* string 9 'C' */
  4564. 1, 1, /* string a 'D' */
  4565. 3, 1, /* string b 'one' */
  4566. 3, 1, /* string c 'two' */
  4567. 0, 0, /* string d '' */
  4568. 4, 1, /* string e 'four' */
  4569. 4, 1, /* string f 'five' */
  4570. };
  4571. static void test_stringtable(void)
  4572. {
  4573. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  4574. IStorage *stg = NULL;
  4575. IStream *stm;
  4576. WCHAR name[0x20];
  4577. HRESULT hr;
  4578. const char *query;
  4579. char buffer[MAX_PATH];
  4580. WCHAR data[MAX_PATH];
  4581. DWORD sz, read;
  4582. UINT r;
  4583. static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
  4584. static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
  4585. static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
  4586. static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
  4587. static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
  4588. DeleteFile(msifile);
  4589. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  4590. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4591. query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
  4592. r = run_query(hdb, 0, query);
  4593. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4594. query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
  4595. r = run_query(hdb, 0, query);
  4596. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4597. /* insert persistent row */
  4598. query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
  4599. r = run_query(hdb, 0, query);
  4600. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4601. /* insert persistent row */
  4602. query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
  4603. r = run_query(hdb, 0, query);
  4604. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4605. /* open a view */
  4606. query = "SELECT * FROM `MOO`";
  4607. r = MsiDatabaseOpenView(hdb, query, &hview);
  4608. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4609. r = MsiViewExecute(hview, 0);
  4610. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4611. hrec = MsiCreateRecord(2);
  4612. r = MsiRecordSetInteger(hrec, 1, 3);
  4613. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4614. r = MsiRecordSetString(hrec, 2, "three");
  4615. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4616. /* insert a nonpersistent row */
  4617. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
  4618. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4619. r = MsiCloseHandle(hrec);
  4620. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4621. r = MsiViewClose(hview);
  4622. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4623. r = MsiCloseHandle(hview);
  4624. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4625. /* insert persistent row */
  4626. query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
  4627. r = run_query(hdb, 0, query);
  4628. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4629. /* insert persistent row */
  4630. query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
  4631. r = run_query(hdb, 0, query);
  4632. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4633. r = MsiDatabaseCommit(hdb);
  4634. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4635. r = MsiCloseHandle(hdb);
  4636. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4637. r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
  4638. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4639. query = "SELECT * FROM `MOO`";
  4640. r = MsiDatabaseOpenView(hdb, query, &hview);
  4641. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4642. r = MsiViewExecute(hview, 0);
  4643. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4644. r = MsiViewFetch(hview, &hrec);
  4645. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4646. r = MsiRecordGetFieldCount(hrec);
  4647. ok(r == 2, "Expected 2, got %d\n", r);
  4648. r = MsiRecordGetInteger(hrec, 1);
  4649. ok(r == 1, "Expected 1, got %d\n", r);
  4650. sz = sizeof(buffer);
  4651. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  4652. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4653. ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
  4654. r = MsiCloseHandle(hrec);
  4655. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4656. r = MsiViewFetch(hview, &hrec);
  4657. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4658. r = MsiViewClose(hview);
  4659. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4660. r = MsiCloseHandle(hview);
  4661. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4662. r = MsiCloseHandle(hrec);
  4663. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4664. query = "SELECT * FROM `AAR`";
  4665. r = MsiDatabaseOpenView(hdb, query, &hview);
  4666. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4667. r = MsiViewExecute(hview, 0);
  4668. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4669. r = MsiViewFetch(hview, &hrec);
  4670. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4671. r = MsiRecordGetFieldCount(hrec);
  4672. ok(r == 2, "Expected 2, got %d\n", r);
  4673. r = MsiRecordGetInteger(hrec, 1);
  4674. ok(r == 2, "Expected 2, got %d\n", r);
  4675. sz = sizeof(buffer);
  4676. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  4677. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4678. ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
  4679. r = MsiCloseHandle(hrec);
  4680. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4681. r = MsiViewFetch(hview, &hrec);
  4682. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4683. r = MsiRecordGetFieldCount(hrec);
  4684. ok(r == 2, "Expected 2, got %d\n", r);
  4685. r = MsiRecordGetInteger(hrec, 1);
  4686. ok(r == 5, "Expected 5, got %d\n", r);
  4687. sz = sizeof(buffer);
  4688. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  4689. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4690. ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
  4691. r = MsiCloseHandle(hrec);
  4692. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4693. r = MsiViewFetch(hview, &hrec);
  4694. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4695. r = MsiViewClose(hview);
  4696. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4697. r = MsiCloseHandle(hview);
  4698. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4699. r = MsiCloseHandle(hrec);
  4700. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4701. r = MsiCloseHandle(hdb);
  4702. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4703. MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
  4704. hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
  4705. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4706. ok(stg != NULL, "Expected non-NULL storage\n");
  4707. hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
  4708. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4709. ok(stm != NULL, "Expected non-NULL stream\n");
  4710. hr = IStream_Read(stm, data, MAX_PATH, &read);
  4711. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4712. ok(read == 4, "Expected 4, got %d\n", read);
  4713. todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
  4714. hr = IStream_Release(stm);
  4715. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4716. hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
  4717. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4718. ok(stm != NULL, "Expected non-NULL stream\n");
  4719. hr = IStream_Read(stm, data, MAX_PATH, &read);
  4720. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4721. ok(read == 8, "Expected 8, got %d\n", read);
  4722. todo_wine
  4723. {
  4724. ok(!memcmp(data, data11, read), "Unexpected data\n");
  4725. }
  4726. hr = IStream_Release(stm);
  4727. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4728. hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
  4729. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4730. ok(stm != NULL, "Expected non-NULL stream\n");
  4731. hr = IStream_Read(stm, buffer, MAX_PATH, &read);
  4732. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4733. ok(read == 24, "Expected 24, got %d\n", read);
  4734. ok(!memcmp(buffer, data12, read), "Unexpected data\n");
  4735. hr = IStream_Release(stm);
  4736. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4737. hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
  4738. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4739. ok(stm != NULL, "Expected non-NULL stream\n");
  4740. hr = IStream_Read(stm, data, MAX_PATH, &read);
  4741. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4742. todo_wine
  4743. {
  4744. ok(read == 64, "Expected 64, got %d\n", read);
  4745. ok(!memcmp(data, data13, read), "Unexpected data\n");
  4746. }
  4747. hr = IStream_Release(stm);
  4748. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4749. hr = IStorage_Release(stg);
  4750. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  4751. DeleteFileA(msifile);
  4752. }
  4753. static void test_viewmodify_delete(void)
  4754. {
  4755. MSIHANDLE hdb = 0, hview = 0, hrec = 0;
  4756. UINT r;
  4757. const char *query;
  4758. char buffer[0x100];
  4759. DWORD sz;
  4760. DeleteFile(msifile);
  4761. /* just MsiOpenDatabase should not create a file */
  4762. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  4763. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4764. query = "CREATE TABLE `phone` ( "
  4765. "`id` INT, `name` CHAR(32), `number` CHAR(32) "
  4766. "PRIMARY KEY `id`)";
  4767. r = run_query(hdb, 0, query);
  4768. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4769. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  4770. "VALUES('1', 'Alan', '5030581')";
  4771. r = run_query(hdb, 0, query);
  4772. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4773. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  4774. "VALUES('2', 'Barry', '928440')";
  4775. r = run_query(hdb, 0, query);
  4776. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4777. query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
  4778. "VALUES('3', 'Cindy', '2937550')";
  4779. r = run_query(hdb, 0, query);
  4780. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4781. query = "SELECT * FROM `phone` WHERE `id` <= 2";
  4782. r = MsiDatabaseOpenView(hdb, query, &hview);
  4783. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4784. r = MsiViewExecute(hview, 0);
  4785. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4786. r = MsiViewFetch(hview, &hrec);
  4787. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4788. /* delete 1 */
  4789. r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
  4790. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4791. r = MsiCloseHandle(hrec);
  4792. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4793. r = MsiViewFetch(hview, &hrec);
  4794. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4795. /* delete 2 */
  4796. r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
  4797. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4798. r = MsiCloseHandle(hrec);
  4799. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4800. r = MsiViewClose(hview);
  4801. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4802. r = MsiCloseHandle(hview);
  4803. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4804. query = "SELECT * FROM `phone`";
  4805. r = MsiDatabaseOpenView(hdb, query, &hview);
  4806. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4807. r = MsiViewExecute(hview, 0);
  4808. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4809. r = MsiViewFetch(hview, &hrec);
  4810. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4811. r = MsiRecordGetInteger(hrec, 1);
  4812. ok(r == 3, "Expected 3, got %d\n", r);
  4813. sz = sizeof(buffer);
  4814. r = MsiRecordGetString(hrec, 2, buffer, &sz);
  4815. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4816. ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
  4817. sz = sizeof(buffer);
  4818. r = MsiRecordGetString(hrec, 3, buffer, &sz);
  4819. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4820. ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
  4821. r = MsiCloseHandle(hrec);
  4822. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4823. r = MsiViewFetch(hview, &hrec);
  4824. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4825. r = MsiViewClose(hview);
  4826. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4827. r = MsiCloseHandle(hview);
  4828. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4829. r = MsiCloseHandle(hdb);
  4830. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4831. }
  4832. static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
  4833. static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
  4834. static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
  4835. static const WCHAR data14[] = { /* _StringPool */
  4836. /* len, refs */
  4837. 0, 0, /* string 0 '' */
  4838. };
  4839. static const struct {
  4840. LPCWSTR name;
  4841. const void *data;
  4842. DWORD size;
  4843. } database_table_data[] =
  4844. {
  4845. {_Tables, NULL, 0},
  4846. {_StringData, NULL, 0},
  4847. {_StringPool, data14, sizeof data14},
  4848. };
  4849. static void enum_stream_names(IStorage *stg)
  4850. {
  4851. IEnumSTATSTG *stgenum = NULL;
  4852. IStream *stm;
  4853. HRESULT hr;
  4854. STATSTG stat;
  4855. ULONG n, count;
  4856. BYTE data[MAX_PATH];
  4857. BYTE check[MAX_PATH];
  4858. DWORD sz;
  4859. memset(check, 'a', MAX_PATH);
  4860. hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
  4861. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  4862. n = 0;
  4863. while(TRUE)
  4864. {
  4865. count = 0;
  4866. hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
  4867. if(FAILED(hr) || !count)
  4868. break;
  4869. ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
  4870. "Expected table %d name to match\n", n);
  4871. stm = NULL;
  4872. hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
  4873. STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
  4874. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  4875. ok(stm != NULL, "Expected non-NULL stream\n");
  4876. CoTaskMemFree(stat.pwcsName);
  4877. sz = MAX_PATH;
  4878. memset(data, 'a', MAX_PATH);
  4879. hr = IStream_Read(stm, data, sz, &count);
  4880. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  4881. ok(count == database_table_data[n].size,
  4882. "Expected %d, got %d\n", database_table_data[n].size, count);
  4883. if (!database_table_data[n].size)
  4884. ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
  4885. else
  4886. ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
  4887. "Expected table %d data to match\n", n);
  4888. IStream_Release(stm);
  4889. n++;
  4890. }
  4891. ok(n == 3, "Expected 3, got %d\n", n);
  4892. IEnumSTATSTG_Release(stgenum);
  4893. }
  4894. static void test_defaultdatabase(void)
  4895. {
  4896. UINT r;
  4897. HRESULT hr;
  4898. MSIHANDLE hdb;
  4899. IStorage *stg = NULL;
  4900. DeleteFile(msifile);
  4901. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  4902. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4903. r = MsiDatabaseCommit(hdb);
  4904. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4905. MsiCloseHandle(hdb);
  4906. hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
  4907. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  4908. ok(stg != NULL, "Expected non-NULL stg\n");
  4909. enum_stream_names(stg);
  4910. IStorage_Release(stg);
  4911. DeleteFileA(msifile);
  4912. }
  4913. static void test_order(void)
  4914. {
  4915. MSIHANDLE hdb, hview, hrec;
  4916. CHAR buffer[MAX_PATH];
  4917. LPCSTR query;
  4918. UINT r, sz;
  4919. int val;
  4920. hdb = create_db();
  4921. ok(hdb, "failed to create db\n");
  4922. query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
  4923. r = run_query(hdb, 0, query);
  4924. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4925. query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
  4926. r = run_query(hdb, 0, query);
  4927. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4928. query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
  4929. r = run_query(hdb, 0, query);
  4930. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4931. query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
  4932. r = run_query(hdb, 0, query);
  4933. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4934. query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
  4935. r = run_query(hdb, 0, query);
  4936. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4937. query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
  4938. r = run_query(hdb, 0, query);
  4939. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4940. query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
  4941. r = run_query(hdb, 0, query);
  4942. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4943. query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
  4944. r = run_query(hdb, 0, query);
  4945. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4946. query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
  4947. r = run_query(hdb, 0, query);
  4948. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4949. query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
  4950. r = MsiDatabaseOpenView(hdb, query, &hview);
  4951. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4952. r = MsiViewExecute(hview, 0);
  4953. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4954. r = MsiViewFetch(hview, &hrec);
  4955. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4956. val = MsiRecordGetInteger(hrec, 1);
  4957. ok(val == 3, "Expected 3, got %d\n", val);
  4958. val = MsiRecordGetInteger(hrec, 2);
  4959. ok(val == 4, "Expected 3, got %d\n", val);
  4960. MsiCloseHandle(hrec);
  4961. r = MsiViewFetch(hview, &hrec);
  4962. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4963. val = MsiRecordGetInteger(hrec, 1);
  4964. ok(val == 5, "Expected 5, got %d\n", val);
  4965. val = MsiRecordGetInteger(hrec, 2);
  4966. ok(val == 6, "Expected 6, got %d\n", val);
  4967. MsiCloseHandle(hrec);
  4968. r = MsiViewFetch(hview, &hrec);
  4969. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4970. val = MsiRecordGetInteger(hrec, 1);
  4971. ok(val == 1, "Expected 1, got %d\n", val);
  4972. val = MsiRecordGetInteger(hrec, 2);
  4973. ok(val == 2, "Expected 2, got %d\n", val);
  4974. MsiCloseHandle(hrec);
  4975. r = MsiViewFetch(hview, &hrec);
  4976. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  4977. MsiViewClose(hview);
  4978. MsiCloseHandle(hview);
  4979. query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
  4980. r = MsiDatabaseOpenView(hdb, query, &hview);
  4981. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4982. r = MsiViewExecute(hview, 0);
  4983. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4984. r = MsiViewFetch(hview, &hrec);
  4985. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4986. val = MsiRecordGetInteger(hrec, 1);
  4987. ok(val == 1, "Expected 1, got %d\n", val);
  4988. val = MsiRecordGetInteger(hrec, 2);
  4989. ok(val == 12, "Expected 12, got %d\n", val);
  4990. MsiCloseHandle(hrec);
  4991. r = MsiViewFetch(hview, &hrec);
  4992. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  4993. val = MsiRecordGetInteger(hrec, 1);
  4994. ok(val == 3, "Expected 3, got %d\n", val);
  4995. val = MsiRecordGetInteger(hrec, 2);
  4996. ok(val == 12, "Expected 12, got %d\n", val);
  4997. MsiCloseHandle(hrec);
  4998. r = MsiViewFetch(hview, &hrec);
  4999. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5000. val = MsiRecordGetInteger(hrec, 1);
  5001. ok(val == 5, "Expected 5, got %d\n", val);
  5002. val = MsiRecordGetInteger(hrec, 2);
  5003. ok(val == 12, "Expected 12, got %d\n", val);
  5004. MsiCloseHandle(hrec);
  5005. r = MsiViewFetch(hview, &hrec);
  5006. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5007. val = MsiRecordGetInteger(hrec, 1);
  5008. ok(val == 1, "Expected 1, got %d\n", val);
  5009. val = MsiRecordGetInteger(hrec, 2);
  5010. ok(val == 14, "Expected 14, got %d\n", val);
  5011. MsiCloseHandle(hrec);
  5012. r = MsiViewFetch(hview, &hrec);
  5013. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5014. val = MsiRecordGetInteger(hrec, 1);
  5015. ok(val == 3, "Expected 3, got %d\n", val);
  5016. val = MsiRecordGetInteger(hrec, 2);
  5017. ok(val == 14, "Expected 14, got %d\n", val);
  5018. MsiCloseHandle(hrec);
  5019. r = MsiViewFetch(hview, &hrec);
  5020. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5021. val = MsiRecordGetInteger(hrec, 1);
  5022. ok(val == 5, "Expected 5, got %d\n", val);
  5023. val = MsiRecordGetInteger(hrec, 2);
  5024. ok(val == 14, "Expected 14, got %d\n", val);
  5025. MsiCloseHandle(hrec);
  5026. r = MsiViewFetch(hview, &hrec);
  5027. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5028. val = MsiRecordGetInteger(hrec, 1);
  5029. ok(val == 1, "Expected 1, got %d\n", val);
  5030. val = MsiRecordGetInteger(hrec, 2);
  5031. ok(val == 10, "Expected 10, got %d\n", val);
  5032. MsiCloseHandle(hrec);
  5033. r = MsiViewFetch(hview, &hrec);
  5034. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5035. val = MsiRecordGetInteger(hrec, 1);
  5036. ok(val == 3, "Expected 3, got %d\n", val);
  5037. val = MsiRecordGetInteger(hrec, 2);
  5038. ok(val == 10, "Expected 10, got %d\n", val);
  5039. MsiCloseHandle(hrec);
  5040. r = MsiViewFetch(hview, &hrec);
  5041. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5042. val = MsiRecordGetInteger(hrec, 1);
  5043. ok(val == 5, "Expected 5, got %d\n", val);
  5044. val = MsiRecordGetInteger(hrec, 2);
  5045. ok(val == 10, "Expected 10, got %d\n", val);
  5046. MsiCloseHandle(hrec);
  5047. r = MsiViewFetch(hview, &hrec);
  5048. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5049. MsiViewClose(hview);
  5050. MsiCloseHandle(hview);
  5051. query = "SELECT * FROM `Empty` ORDER BY `A`";
  5052. r = MsiDatabaseOpenView(hdb, query, &hview);
  5053. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5054. r = MsiViewExecute(hview, 0);
  5055. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5056. r = MsiViewFetch(hview, &hrec);
  5057. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5058. MsiViewClose(hview);
  5059. MsiCloseHandle(hview);
  5060. query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
  5061. r = run_query(hdb, 0, query);
  5062. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5063. query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno', 2)";
  5064. r = run_query(hdb, 0, query);
  5065. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5066. query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos', 3)";
  5067. r = run_query(hdb, 0, query);
  5068. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5069. query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres', 1)";
  5070. r = run_query(hdb, 0, query);
  5071. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5072. query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
  5073. r = MsiDatabaseOpenView(hdb, query, &hview);
  5074. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5075. r = MsiViewExecute(hview, 0);
  5076. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5077. r = MsiViewFetch(hview, &hrec);
  5078. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5079. sz = sizeof(buffer);
  5080. r = MsiRecordGetString(hrec, 1, buffer, &sz);
  5081. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5082. ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
  5083. r = MsiRecordGetInteger(hrec, 2);
  5084. ok(r == 3, "Expected 3, got %d\n", r);
  5085. MsiCloseHandle(hrec);
  5086. r = MsiViewFetch(hview, &hrec);
  5087. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5088. MsiViewClose(hview);
  5089. MsiCloseHandle(hview);
  5090. MsiCloseHandle(hdb);
  5091. }
  5092. static void test_viewmodify_delete_temporary(void)
  5093. {
  5094. MSIHANDLE hdb, hview, hrec;
  5095. const char *query;
  5096. UINT r;
  5097. DeleteFile(msifile);
  5098. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5099. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5100. query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
  5101. r = run_query(hdb, 0, query);
  5102. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5103. query = "SELECT * FROM `Table`";
  5104. r = MsiDatabaseOpenView(hdb, query, &hview);
  5105. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5106. r = MsiViewExecute(hview, 0);
  5107. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5108. hrec = MsiCreateRecord(1);
  5109. MsiRecordSetInteger(hrec, 1, 1);
  5110. r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
  5111. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5112. MsiCloseHandle(hrec);
  5113. hrec = MsiCreateRecord(1);
  5114. MsiRecordSetInteger(hrec, 1, 2);
  5115. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
  5116. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5117. MsiCloseHandle(hrec);
  5118. hrec = MsiCreateRecord(1);
  5119. MsiRecordSetInteger(hrec, 1, 3);
  5120. r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
  5121. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5122. MsiCloseHandle(hrec);
  5123. hrec = MsiCreateRecord(1);
  5124. MsiRecordSetInteger(hrec, 1, 4);
  5125. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
  5126. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5127. MsiCloseHandle(hrec);
  5128. MsiViewClose(hview);
  5129. MsiCloseHandle(hview);
  5130. query = "SELECT * FROM `Table` WHERE `A` = 2";
  5131. r = MsiDatabaseOpenView(hdb, query, &hview);
  5132. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5133. r = MsiViewExecute(hview, 0);
  5134. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5135. r = MsiViewFetch(hview, &hrec);
  5136. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5137. r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
  5138. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5139. MsiCloseHandle(hrec);
  5140. MsiViewClose(hview);
  5141. MsiCloseHandle(hview);
  5142. query = "SELECT * FROM `Table` WHERE `A` = 3";
  5143. r = MsiDatabaseOpenView(hdb, query, &hview);
  5144. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5145. r = MsiViewExecute(hview, 0);
  5146. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5147. r = MsiViewFetch(hview, &hrec);
  5148. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5149. r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
  5150. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5151. MsiCloseHandle(hrec);
  5152. MsiViewClose(hview);
  5153. MsiCloseHandle(hview);
  5154. query = "SELECT * FROM `Table` ORDER BY `A`";
  5155. r = MsiDatabaseOpenView(hdb, query, &hview);
  5156. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5157. r = MsiViewExecute(hview, 0);
  5158. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5159. r = MsiViewFetch(hview, &hrec);
  5160. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5161. r = MsiRecordGetInteger(hrec, 1);
  5162. ok(r == 1, "Expected 1, got %d\n", r);
  5163. MsiCloseHandle(hrec);
  5164. r = MsiViewFetch(hview, &hrec);
  5165. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5166. r = MsiRecordGetInteger(hrec, 1);
  5167. ok(r == 4, "Expected 4, got %d\n", r);
  5168. MsiCloseHandle(hrec);
  5169. r = MsiViewFetch(hview, &hrec);
  5170. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5171. MsiViewClose(hview);
  5172. MsiCloseHandle(hview);
  5173. MsiCloseHandle(hdb);
  5174. DeleteFileA(msifile);
  5175. }
  5176. static void test_deleterow(void)
  5177. {
  5178. MSIHANDLE hdb, hview, hrec;
  5179. const char *query;
  5180. char buf[MAX_PATH];
  5181. UINT r;
  5182. DWORD size;
  5183. DeleteFile(msifile);
  5184. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5185. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5186. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5187. r = run_query(hdb, 0, query);
  5188. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5189. query = "INSERT INTO `Table` (`A`) VALUES ('one')";
  5190. r = run_query(hdb, 0, query);
  5191. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5192. query = "INSERT INTO `Table` (`A`) VALUES ('two')";
  5193. r = run_query(hdb, 0, query);
  5194. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5195. query = "DELETE FROM `Table` WHERE `A` = 'one'";
  5196. r = run_query(hdb, 0, query);
  5197. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5198. r = MsiDatabaseCommit(hdb);
  5199. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5200. MsiCloseHandle(hdb);
  5201. r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
  5202. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5203. query = "SELECT * FROM `Table`";
  5204. r = MsiDatabaseOpenView(hdb, query, &hview);
  5205. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5206. r = MsiViewExecute(hview, 0);
  5207. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5208. r = MsiViewFetch(hview, &hrec);
  5209. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5210. size = MAX_PATH;
  5211. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5212. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5213. ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
  5214. MsiCloseHandle(hrec);
  5215. r = MsiViewFetch(hview, &hrec);
  5216. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5217. MsiViewClose(hview);
  5218. MsiCloseHandle(hview);
  5219. MsiCloseHandle(hdb);
  5220. DeleteFileA(msifile);
  5221. }
  5222. static const CHAR import_dat[] = "A\n"
  5223. "s72\n"
  5224. "Table\tA\n"
  5225. "This is a new 'string' ok\n";
  5226. static void test_quotes(void)
  5227. {
  5228. MSIHANDLE hdb, hview, hrec;
  5229. const char *query;
  5230. char buf[MAX_PATH];
  5231. UINT r;
  5232. DWORD size;
  5233. DeleteFile(msifile);
  5234. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5235. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5236. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5237. r = run_query(hdb, 0, query);
  5238. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5239. query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
  5240. r = run_query(hdb, 0, query);
  5241. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5242. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5243. query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
  5244. r = run_query(hdb, 0, query);
  5245. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5246. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5247. query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
  5248. r = run_query(hdb, 0, query);
  5249. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5250. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5251. query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
  5252. r = run_query(hdb, 0, query);
  5253. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5254. query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
  5255. r = run_query(hdb, 0, query);
  5256. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5257. query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
  5258. r = run_query(hdb, 0, query);
  5259. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5260. query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
  5261. r = run_query(hdb, 0, query);
  5262. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5263. query = "SELECT * FROM `Table`";
  5264. r = MsiDatabaseOpenView(hdb, query, &hview);
  5265. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5266. r = MsiViewExecute(hview, 0);
  5267. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5268. r = MsiViewFetch(hview, &hrec);
  5269. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5270. size = MAX_PATH;
  5271. r = MsiRecordGetString(hrec, 1, buf, &size);
  5272. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5273. ok(!lstrcmp(buf, "This is a \"string\" ok"),
  5274. "Expected \"This is a \"string\" ok\", got %s\n", buf);
  5275. MsiCloseHandle(hrec);
  5276. r = MsiViewFetch(hview, &hrec);
  5277. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5278. MsiViewClose(hview);
  5279. MsiCloseHandle(hview);
  5280. write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
  5281. r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
  5282. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5283. DeleteFileA("import.idt");
  5284. query = "SELECT * FROM `Table`";
  5285. r = MsiDatabaseOpenView(hdb, query, &hview);
  5286. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5287. r = MsiViewExecute(hview, 0);
  5288. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5289. r = MsiViewFetch(hview, &hrec);
  5290. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5291. size = MAX_PATH;
  5292. r = MsiRecordGetString(hrec, 1, buf, &size);
  5293. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5294. ok(!lstrcmp(buf, "This is a new 'string' ok"),
  5295. "Expected \"This is a new 'string' ok\", got %s\n", buf);
  5296. MsiCloseHandle(hrec);
  5297. r = MsiViewFetch(hview, &hrec);
  5298. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5299. MsiViewClose(hview);
  5300. MsiCloseHandle(hview);
  5301. MsiCloseHandle(hdb);
  5302. DeleteFileA(msifile);
  5303. }
  5304. static void test_carriagereturn(void)
  5305. {
  5306. MSIHANDLE hdb, hview, hrec;
  5307. const char *query;
  5308. char buf[MAX_PATH];
  5309. UINT r;
  5310. DWORD size;
  5311. DeleteFile(msifile);
  5312. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5313. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5314. query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5315. r = run_query(hdb, 0, query);
  5316. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5317. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5318. query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5319. r = run_query(hdb, 0, query);
  5320. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5321. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5322. query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5323. r = run_query(hdb, 0, query);
  5324. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5325. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5326. query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5327. r = run_query(hdb, 0, query);
  5328. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5329. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5330. query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5331. r = run_query(hdb, 0, query);
  5332. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5333. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5334. query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5335. r = run_query(hdb, 0, query);
  5336. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5337. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5338. query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
  5339. r = run_query(hdb, 0, query);
  5340. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5341. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5342. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
  5343. r = run_query(hdb, 0, query);
  5344. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5345. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5346. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
  5347. r = run_query(hdb, 0, query);
  5348. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5349. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5350. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
  5351. r = run_query(hdb, 0, query);
  5352. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5353. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5354. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
  5355. r = run_query(hdb, 0, query);
  5356. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5357. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5358. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
  5359. r = run_query(hdb, 0, query);
  5360. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5361. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5362. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
  5363. r = run_query(hdb, 0, query);
  5364. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5365. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5366. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
  5367. r = run_query(hdb, 0, query);
  5368. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5369. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5370. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
  5371. r = run_query(hdb, 0, query);
  5372. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5373. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5374. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
  5375. r = run_query(hdb, 0, query);
  5376. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5377. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5378. query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5379. r = run_query(hdb, 0, query);
  5380. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5381. query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5382. r = run_query(hdb, 0, query);
  5383. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5384. query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5385. r = run_query(hdb, 0, query);
  5386. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5387. query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5388. r = run_query(hdb, 0, query);
  5389. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5390. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5391. query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5392. r = run_query(hdb, 0, query);
  5393. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5394. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5395. query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
  5396. r = run_query(hdb, 0, query);
  5397. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5398. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5399. query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
  5400. r = run_query(hdb, 0, query);
  5401. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5402. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5403. query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
  5404. r = run_query(hdb, 0, query);
  5405. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5406. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5407. query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
  5408. r = run_query(hdb, 0, query);
  5409. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5410. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5411. query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
  5412. r = run_query(hdb, 0, query);
  5413. ok(r == ERROR_BAD_QUERY_SYNTAX,
  5414. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5415. query = "SELECT * FROM `_Tables`";
  5416. r = MsiDatabaseOpenView(hdb, query, &hview);
  5417. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5418. r = MsiViewExecute(hview, 0);
  5419. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5420. r = MsiViewFetch(hview, &hrec);
  5421. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5422. size = MAX_PATH;
  5423. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5424. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5425. ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
  5426. MsiCloseHandle(hrec);
  5427. r = MsiViewFetch(hview, &hrec);
  5428. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5429. size = MAX_PATH;
  5430. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5431. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5432. ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
  5433. MsiCloseHandle(hrec);
  5434. r = MsiViewFetch(hview, &hrec);
  5435. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5436. size = MAX_PATH;
  5437. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5438. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5439. ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
  5440. MsiCloseHandle(hrec);
  5441. r = MsiViewFetch(hview, &hrec);
  5442. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5443. MsiViewClose(hview);
  5444. MsiCloseHandle(hview);
  5445. MsiCloseHandle(hdb);
  5446. DeleteFileA(msifile);
  5447. }
  5448. static void test_noquotes(void)
  5449. {
  5450. MSIHANDLE hdb, hview, hrec;
  5451. const char *query;
  5452. char buf[MAX_PATH];
  5453. UINT r;
  5454. DWORD size;
  5455. DeleteFile(msifile);
  5456. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5457. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5458. query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5459. r = run_query(hdb, 0, query);
  5460. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5461. query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5462. r = run_query(hdb, 0, query);
  5463. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5464. query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
  5465. r = run_query(hdb, 0, query);
  5466. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5467. query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
  5468. r = run_query(hdb, 0, query);
  5469. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5470. query = "SELECT * FROM `_Tables`";
  5471. r = MsiDatabaseOpenView(hdb, query, &hview);
  5472. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5473. r = MsiViewExecute(hview, 0);
  5474. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5475. r = MsiViewFetch(hview, &hrec);
  5476. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5477. size = MAX_PATH;
  5478. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5479. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5480. ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
  5481. MsiCloseHandle(hrec);
  5482. r = MsiViewFetch(hview, &hrec);
  5483. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5484. size = MAX_PATH;
  5485. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5486. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5487. ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
  5488. MsiCloseHandle(hrec);
  5489. r = MsiViewFetch(hview, &hrec);
  5490. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5491. size = MAX_PATH;
  5492. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5493. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5494. ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
  5495. MsiCloseHandle(hrec);
  5496. r = MsiViewFetch(hview, &hrec);
  5497. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5498. MsiViewClose(hview);
  5499. MsiCloseHandle(hview);
  5500. query = "SELECT * FROM `_Columns`";
  5501. r = MsiDatabaseOpenView(hdb, query, &hview);
  5502. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5503. r = MsiViewExecute(hview, 0);
  5504. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5505. r = MsiViewFetch(hview, &hrec);
  5506. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5507. size = MAX_PATH;
  5508. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5509. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5510. ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
  5511. r = MsiRecordGetInteger(hrec, 2);
  5512. ok(r == 1, "Expected 1, got %d\n", r);
  5513. size = MAX_PATH;
  5514. r = MsiRecordGetStringA(hrec, 3, buf, &size);
  5515. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5516. ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
  5517. MsiCloseHandle(hrec);
  5518. r = MsiViewFetch(hview, &hrec);
  5519. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5520. size = MAX_PATH;
  5521. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5522. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5523. ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
  5524. r = MsiRecordGetInteger(hrec, 2);
  5525. ok(r == 1, "Expected 1, got %d\n", r);
  5526. size = MAX_PATH;
  5527. r = MsiRecordGetStringA(hrec, 3, buf, &size);
  5528. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5529. ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
  5530. MsiCloseHandle(hrec);
  5531. r = MsiViewFetch(hview, &hrec);
  5532. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5533. size = MAX_PATH;
  5534. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5535. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5536. ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
  5537. r = MsiRecordGetInteger(hrec, 2);
  5538. ok(r == 1, "Expected 1, got %d\n", r);
  5539. size = MAX_PATH;
  5540. r = MsiRecordGetStringA(hrec, 3, buf, &size);
  5541. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5542. ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
  5543. MsiCloseHandle(hrec);
  5544. r = MsiViewFetch(hview, &hrec);
  5545. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5546. MsiViewClose(hview);
  5547. MsiCloseHandle(hview);
  5548. query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
  5549. r = run_query(hdb, 0, query);
  5550. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5551. query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
  5552. r = run_query(hdb, 0, query);
  5553. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5554. query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
  5555. r = run_query(hdb, 0, query);
  5556. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5557. query = "SELECT * FROM Table WHERE `A` = 'hi'";
  5558. r = run_query(hdb, 0, query);
  5559. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5560. query = "SELECT * FROM `Table` WHERE `A` = hi";
  5561. r = run_query(hdb, 0, query);
  5562. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5563. query = "SELECT * FROM Table";
  5564. r = run_query(hdb, 0, query);
  5565. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5566. query = "SELECT * FROM Table2";
  5567. r = MsiDatabaseOpenView(hdb, query, &hview);
  5568. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5569. r = MsiViewExecute(hview, 0);
  5570. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5571. r = MsiViewFetch(hview, &hrec);
  5572. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5573. MsiViewClose(hview);
  5574. MsiCloseHandle(hview);
  5575. query = "SELECT * FROM `Table` WHERE A = 'hi'";
  5576. r = MsiDatabaseOpenView(hdb, query, &hview);
  5577. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5578. r = MsiViewExecute(hview, 0);
  5579. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5580. r = MsiViewFetch(hview, &hrec);
  5581. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5582. size = MAX_PATH;
  5583. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  5584. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5585. ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
  5586. MsiCloseHandle(hrec);
  5587. r = MsiViewFetch(hview, &hrec);
  5588. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5589. MsiViewClose(hview);
  5590. MsiCloseHandle(hview);
  5591. MsiCloseHandle(hdb);
  5592. DeleteFileA(msifile);
  5593. }
  5594. static void read_file_data(LPCSTR filename, LPSTR buffer)
  5595. {
  5596. HANDLE file;
  5597. DWORD read;
  5598. file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
  5599. ZeroMemory(buffer, MAX_PATH);
  5600. ReadFile(file, buffer, MAX_PATH, &read, NULL);
  5601. CloseHandle(file);
  5602. }
  5603. static void test_forcecodepage(void)
  5604. {
  5605. MSIHANDLE hdb;
  5606. const char *query;
  5607. char buffer[MAX_PATH];
  5608. UINT r;
  5609. DeleteFile(msifile);
  5610. GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
  5611. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5612. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5613. query = "SELECT * FROM `_ForceCodepage`";
  5614. r = run_query(hdb, 0, query);
  5615. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5616. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
  5617. r = run_query(hdb, 0, query);
  5618. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5619. query = "SELECT * FROM `_ForceCodepage`";
  5620. r = run_query(hdb, 0, query);
  5621. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5622. r = MsiDatabaseCommit(hdb);
  5623. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5624. query = "SELECT * FROM `_ForceCodepage`";
  5625. r = run_query(hdb, 0, query);
  5626. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5627. MsiCloseHandle(hdb);
  5628. r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb);
  5629. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5630. query = "SELECT * FROM `_ForceCodepage`";
  5631. r = run_query(hdb, 0, query);
  5632. ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  5633. r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
  5634. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5635. read_file_data("forcecodepage.idt", buffer);
  5636. ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
  5637. "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
  5638. create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
  5639. r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
  5640. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5641. r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
  5642. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5643. read_file_data("forcecodepage.idt", buffer);
  5644. ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
  5645. "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
  5646. create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
  5647. r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
  5648. ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_SUCCESS, got %d\n", r);
  5649. MsiCloseHandle(hdb);
  5650. DeleteFileA(msifile);
  5651. DeleteFileA("forcecodepage.idt");
  5652. }
  5653. static void test_viewmodify_refresh(void)
  5654. {
  5655. MSIHANDLE hdb, hview, hrec;
  5656. const char *query;
  5657. char buffer[MAX_PATH];
  5658. UINT r;
  5659. DWORD size;
  5660. DeleteFile(msifile);
  5661. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5662. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5663. query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
  5664. r = run_query(hdb, 0, query);
  5665. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5666. query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
  5667. r = run_query(hdb, 0, query);
  5668. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5669. query = "SELECT * FROM `Table`";
  5670. r = MsiDatabaseOpenView(hdb, query, &hview);
  5671. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5672. r = MsiViewExecute(hview, 0);
  5673. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5674. r = MsiViewFetch(hview, &hrec);
  5675. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5676. query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
  5677. r = run_query(hdb, 0, query);
  5678. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5679. r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
  5680. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5681. size = MAX_PATH;
  5682. r = MsiRecordGetStringA(hrec, 1, buffer, &size);
  5683. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5684. ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
  5685. ok(size == 2, "Expected 2, got %d\n", size);
  5686. r = MsiRecordGetInteger(hrec, 2);
  5687. ok(r == 2, "Expected 2, got %d\n", r);
  5688. MsiCloseHandle(hrec);
  5689. MsiViewClose(hview);
  5690. MsiCloseHandle(hview);
  5691. query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
  5692. r = run_query(hdb, 0, query);
  5693. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5694. query = "SELECT * FROM `Table` WHERE `B` = 3";
  5695. r = MsiDatabaseOpenView(hdb, query, &hview);
  5696. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5697. r = MsiViewExecute(hview, 0);
  5698. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5699. r = MsiViewFetch(hview, &hrec);
  5700. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5701. query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
  5702. r = run_query(hdb, 0, query);
  5703. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5704. query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
  5705. r = run_query(hdb, 0, query);
  5706. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5707. r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
  5708. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5709. size = MAX_PATH;
  5710. r = MsiRecordGetStringA(hrec, 1, buffer, &size);
  5711. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5712. ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
  5713. ok(size == 5, "Expected 5, got %d\n", size);
  5714. r = MsiRecordGetInteger(hrec, 2);
  5715. ok(r == 2, "Expected 2, got %d\n", r);
  5716. MsiCloseHandle(hrec);
  5717. MsiViewClose(hview);
  5718. MsiCloseHandle(hview);
  5719. MsiCloseHandle(hdb);
  5720. DeleteFileA(msifile);
  5721. }
  5722. static void test_where_viewmodify(void)
  5723. {
  5724. MSIHANDLE hdb, hview, hrec;
  5725. const char *query;
  5726. UINT r;
  5727. DeleteFile(msifile);
  5728. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5729. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5730. query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  5731. r = run_query(hdb, 0, query);
  5732. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5733. query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
  5734. r = run_query(hdb, 0, query);
  5735. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5736. query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
  5737. r = run_query(hdb, 0, query);
  5738. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5739. query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
  5740. r = run_query(hdb, 0, query);
  5741. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5742. /* `B` = 3 doesn't match, but the view shouldn't be executed */
  5743. query = "SELECT * FROM `Table` WHERE `B` = 3";
  5744. r = MsiDatabaseOpenView(hdb, query, &hview);
  5745. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5746. hrec = MsiCreateRecord(2);
  5747. MsiRecordSetInteger(hrec, 1, 7);
  5748. MsiRecordSetInteger(hrec, 2, 8);
  5749. r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
  5750. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5751. MsiCloseHandle(hrec);
  5752. MsiViewClose(hview);
  5753. MsiCloseHandle(hview);
  5754. query = "SELECT * FROM `Table` WHERE `A` = 7";
  5755. r = MsiDatabaseOpenView(hdb, query, &hview);
  5756. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5757. r = MsiViewExecute(hview, 0);
  5758. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5759. r = MsiViewFetch(hview, &hrec);
  5760. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5761. r = MsiRecordGetInteger(hrec, 1);
  5762. ok(r == 7, "Expected 7, got %d\n", r);
  5763. r = MsiRecordGetInteger(hrec, 2);
  5764. ok(r == 8, "Expected 8, got %d\n", r);
  5765. MsiRecordSetInteger(hrec, 2, 9);
  5766. r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
  5767. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5768. MsiCloseHandle(hrec);
  5769. MsiViewClose(hview);
  5770. MsiCloseHandle(hview);
  5771. query = "SELECT * FROM `Table` WHERE `A` = 7";
  5772. r = MsiDatabaseOpenView(hdb, query, &hview);
  5773. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5774. r = MsiViewExecute(hview, 0);
  5775. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5776. r = MsiViewFetch(hview, &hrec);
  5777. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5778. r = MsiRecordGetInteger(hrec, 1);
  5779. ok(r == 7, "Expected 7, got %d\n", r);
  5780. r = MsiRecordGetInteger(hrec, 2);
  5781. ok(r == 9, "Expected 9, got %d\n", r);
  5782. query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
  5783. r = run_query(hdb, 0, query);
  5784. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5785. r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
  5786. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5787. r = MsiRecordGetInteger(hrec, 1);
  5788. ok(r == 7, "Expected 7, got %d\n", r);
  5789. r = MsiRecordGetInteger(hrec, 2);
  5790. ok(r == 10, "Expected 10, got %d\n", r);
  5791. MsiCloseHandle(hrec);
  5792. MsiViewClose(hview);
  5793. MsiCloseHandle(hview);
  5794. MsiCloseHandle(hdb);
  5795. }
  5796. static BOOL create_storage(LPCSTR name)
  5797. {
  5798. WCHAR nameW[MAX_PATH];
  5799. IStorage *stg;
  5800. IStream *stm;
  5801. HRESULT hr;
  5802. DWORD count;
  5803. BOOL res = FALSE;
  5804. MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
  5805. hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
  5806. STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
  5807. if (FAILED(hr))
  5808. return FALSE;
  5809. hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
  5810. 0, 0, &stm);
  5811. if (FAILED(hr))
  5812. goto done;
  5813. hr = IStream_Write(stm, "stgdata", 8, &count);
  5814. if (SUCCEEDED(hr))
  5815. res = TRUE;
  5816. done:
  5817. IStream_Release(stm);
  5818. IStorage_Release(stg);
  5819. return res;
  5820. }
  5821. static void test_storages_table(void)
  5822. {
  5823. MSIHANDLE hdb, hview, hrec;
  5824. IStorage *stg, *inner;
  5825. IStream *stm;
  5826. char file[MAX_PATH];
  5827. char buf[MAX_PATH];
  5828. WCHAR name[MAX_PATH];
  5829. LPCSTR query;
  5830. HRESULT hr;
  5831. DWORD size;
  5832. UINT r;
  5833. hdb = create_db();
  5834. ok(hdb, "failed to create db\n");
  5835. r = MsiDatabaseCommit(hdb);
  5836. ok(r == ERROR_SUCCESS , "Failed to commit database\n");
  5837. MsiCloseHandle(hdb);
  5838. r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
  5839. ok(r == ERROR_SUCCESS , "Failed to open database\n");
  5840. /* check the column types */
  5841. hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
  5842. ok(hrec, "failed to get column info hrecord\n");
  5843. ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
  5844. ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
  5845. MsiCloseHandle(hrec);
  5846. /* now try the names */
  5847. hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
  5848. ok(hrec, "failed to get column info hrecord\n");
  5849. ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
  5850. ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
  5851. MsiCloseHandle(hrec);
  5852. create_storage("storage.bin");
  5853. hrec = MsiCreateRecord(2);
  5854. MsiRecordSetString(hrec, 1, "stgname");
  5855. r = MsiRecordSetStream(hrec, 2, "storage.bin");
  5856. ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
  5857. DeleteFileA("storage.bin");
  5858. query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
  5859. r = MsiDatabaseOpenView(hdb, query, &hview);
  5860. ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
  5861. r = MsiViewExecute(hview, hrec);
  5862. ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
  5863. MsiCloseHandle(hrec);
  5864. MsiViewClose(hview);
  5865. MsiCloseHandle(hview);
  5866. query = "SELECT `Name`, `Data` FROM `_Storages`";
  5867. r = MsiDatabaseOpenView(hdb, query, &hview);
  5868. ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
  5869. r = MsiViewExecute(hview, 0);
  5870. ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
  5871. r = MsiViewFetch(hview, &hrec);
  5872. ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
  5873. size = MAX_PATH;
  5874. r = MsiRecordGetString(hrec, 1, file, &size);
  5875. ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
  5876. ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
  5877. size = MAX_PATH;
  5878. lstrcpyA(buf, "apple");
  5879. r = MsiRecordReadStream(hrec, 2, buf, &size);
  5880. ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
  5881. ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
  5882. ok(size == 0, "Expected 0, got %d\n", size);
  5883. MsiCloseHandle(hrec);
  5884. r = MsiViewFetch(hview, &hrec);
  5885. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  5886. MsiViewClose(hview);
  5887. MsiCloseHandle(hview);
  5888. MsiDatabaseCommit(hdb);
  5889. MsiCloseHandle(hdb);
  5890. MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
  5891. hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
  5892. STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
  5893. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  5894. ok(stg != NULL, "Expected non-NULL storage\n");
  5895. MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
  5896. hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
  5897. NULL, 0, &inner);
  5898. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  5899. ok(inner != NULL, "Expected non-NULL storage\n");
  5900. MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
  5901. hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
  5902. ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
  5903. ok(stm != NULL, "Expected non-NULL stream\n");
  5904. hr = IStream_Read(stm, buf, MAX_PATH, &size);
  5905. ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
  5906. ok(size == 8, "Expected 8, got %d\n", size);
  5907. ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
  5908. IStream_Release(stm);
  5909. IStorage_Release(inner);
  5910. IStorage_Release(stg);
  5911. DeleteFileA(msifile);
  5912. }
  5913. static void test_dbtopackage(void)
  5914. {
  5915. MSIHANDLE hdb, hpkg;
  5916. CHAR package[12], buf[MAX_PATH];
  5917. DWORD size;
  5918. UINT r;
  5919. /* create an empty database, transact mode */
  5920. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  5921. ok(r == ERROR_SUCCESS, "Failed to create database\n");
  5922. set_summary_info(hdb);
  5923. r = create_directory_table(hdb);
  5924. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5925. r = create_custom_action_table(hdb);
  5926. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5927. r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
  5928. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5929. sprintf(package, "#%u", hdb);
  5930. r = MsiOpenPackage(package, &hpkg);
  5931. if (r == ERROR_INSTALL_PACKAGE_REJECTED)
  5932. {
  5933. skip("Not enough rights to perform tests\n");
  5934. goto error;
  5935. }
  5936. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5937. /* property is not set yet */
  5938. size = MAX_PATH;
  5939. lstrcpyA(buf, "kiwi");
  5940. r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
  5941. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5942. ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
  5943. ok(size == 0, "Expected 0, got %d\n", size);
  5944. /* run the custom action to set the property */
  5945. r = MsiDoAction(hpkg, "SetProp");
  5946. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5947. /* property is now set */
  5948. size = MAX_PATH;
  5949. lstrcpyA(buf, "kiwi");
  5950. r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
  5951. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5952. ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
  5953. ok(size == 5, "Expected 5, got %d\n", size);
  5954. MsiCloseHandle(hpkg);
  5955. /* reset the package */
  5956. r = MsiOpenPackage(package, &hpkg);
  5957. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5958. /* property is not set anymore */
  5959. size = MAX_PATH;
  5960. lstrcpyA(buf, "kiwi");
  5961. r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
  5962. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5963. todo_wine
  5964. {
  5965. ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
  5966. ok(size == 0, "Expected 0, got %d\n", size);
  5967. }
  5968. MsiCloseHandle(hdb);
  5969. MsiCloseHandle(hpkg);
  5970. /* create an empty database, direct mode */
  5971. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
  5972. ok(r == ERROR_SUCCESS, "Failed to create database\n");
  5973. set_summary_info(hdb);
  5974. r = create_directory_table(hdb);
  5975. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5976. r = create_custom_action_table(hdb);
  5977. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5978. r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
  5979. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5980. sprintf(package, "#%u", hdb);
  5981. r = MsiOpenPackage(package, &hpkg);
  5982. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5983. /* property is not set yet */
  5984. size = MAX_PATH;
  5985. lstrcpyA(buf, "kiwi");
  5986. r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
  5987. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5988. ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
  5989. ok(size == 0, "Expected 0, got %d\n", size);
  5990. /* run the custom action to set the property */
  5991. r = MsiDoAction(hpkg, "SetProp");
  5992. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5993. /* property is now set */
  5994. size = MAX_PATH;
  5995. lstrcpyA(buf, "kiwi");
  5996. r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
  5997. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  5998. ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
  5999. ok(size == 5, "Expected 5, got %d\n", size);
  6000. MsiCloseHandle(hpkg);
  6001. /* reset the package */
  6002. r = MsiOpenPackage(package, &hpkg);
  6003. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6004. /* property is not set anymore */
  6005. size = MAX_PATH;
  6006. lstrcpyA(buf, "kiwi");
  6007. r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
  6008. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6009. todo_wine
  6010. {
  6011. ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
  6012. ok(size == 0, "Expected 0, got %d\n", size);
  6013. }
  6014. MsiCloseHandle(hpkg);
  6015. error:
  6016. MsiCloseHandle(hdb);
  6017. DeleteFileA(msifile);
  6018. }
  6019. static void test_droptable(void)
  6020. {
  6021. MSIHANDLE hdb, hview, hrec;
  6022. CHAR buf[MAX_PATH];
  6023. LPCSTR query;
  6024. DWORD size;
  6025. UINT r;
  6026. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  6027. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6028. query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
  6029. r = run_query(hdb, 0, query);
  6030. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6031. query = "SELECT * FROM `One`";
  6032. r = do_query(hdb, query, &hrec);
  6033. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6034. query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
  6035. r = MsiDatabaseOpenViewA(hdb, query, &hview);
  6036. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6037. r = MsiViewExecute(hview, 0);
  6038. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6039. r = MsiViewFetch(hview, &hrec);
  6040. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6041. size = MAX_PATH;
  6042. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6043. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6044. ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
  6045. MsiCloseHandle(hrec);
  6046. MsiViewClose(hview);
  6047. MsiCloseHandle(hview);
  6048. query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
  6049. r = MsiDatabaseOpenViewA(hdb, query, &hview);
  6050. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6051. r = MsiViewExecute(hview, 0);
  6052. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6053. r = MsiViewFetch(hview, &hrec);
  6054. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6055. size = MAX_PATH;
  6056. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6057. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6058. ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
  6059. r = MsiRecordGetInteger(hrec, 2);
  6060. ok(r == 1, "Expected 1, got %d\n", r);
  6061. size = MAX_PATH;
  6062. r = MsiRecordGetStringA(hrec, 3, buf, &size);
  6063. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6064. ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
  6065. MsiCloseHandle(hrec);
  6066. r = MsiViewFetch(hview, &hrec);
  6067. ok(r == ERROR_NO_MORE_ITEMS,
  6068. "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6069. MsiViewClose(hview);
  6070. MsiCloseHandle(hview);
  6071. query = "DROP `One`";
  6072. r = run_query(hdb, 0, query);
  6073. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6074. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6075. query = "DROP TABLE";
  6076. r = run_query(hdb, 0, query);
  6077. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6078. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6079. query = "DROP TABLE `One`";
  6080. hview = 0;
  6081. r = MsiDatabaseOpenViewA(hdb, query, &hview);
  6082. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6083. r = MsiViewExecute(hview, 0);
  6084. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6085. r = MsiViewFetch(hview, &hrec);
  6086. ok(r == ERROR_FUNCTION_FAILED,
  6087. "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  6088. MsiViewClose(hview);
  6089. MsiCloseHandle(hview);
  6090. query = "SELECT * FROM `IDontExist`";
  6091. r = do_query(hdb, query, &hrec);
  6092. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6093. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6094. query = "SELECT * FROM `One`";
  6095. r = do_query(hdb, query, &hrec);
  6096. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6097. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6098. query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
  6099. r = run_query(hdb, 0, query);
  6100. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6101. query = "DROP TABLE One";
  6102. r = run_query(hdb, 0, query);
  6103. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6104. query = "SELECT * FROM `One`";
  6105. r = do_query(hdb, query, &hrec);
  6106. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6107. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6108. query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
  6109. r = do_query(hdb, query, &hrec);
  6110. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6111. query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
  6112. r = do_query(hdb, query, &hrec);
  6113. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6114. query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
  6115. r = run_query(hdb, 0, query);
  6116. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6117. query = "SELECT * FROM `One`";
  6118. r = do_query(hdb, query, &hrec);
  6119. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6120. query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
  6121. r = MsiDatabaseOpenViewA(hdb, query, &hview);
  6122. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6123. r = MsiViewExecute(hview, 0);
  6124. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6125. r = MsiViewFetch(hview, &hrec);
  6126. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6127. size = MAX_PATH;
  6128. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6129. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6130. ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
  6131. MsiCloseHandle(hrec);
  6132. MsiViewClose(hview);
  6133. MsiCloseHandle(hview);
  6134. query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
  6135. r = MsiDatabaseOpenViewA(hdb, query, &hview);
  6136. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6137. r = MsiViewExecute(hview, 0);
  6138. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6139. r = MsiViewFetch(hview, &hrec);
  6140. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6141. size = MAX_PATH;
  6142. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6143. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6144. ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
  6145. r = MsiRecordGetInteger(hrec, 2);
  6146. ok(r == 1, "Expected 1, got %d\n", r);
  6147. size = MAX_PATH;
  6148. r = MsiRecordGetStringA(hrec, 3, buf, &size);
  6149. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6150. ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
  6151. MsiCloseHandle(hrec);
  6152. r = MsiViewFetch(hview, &hrec);
  6153. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6154. size = MAX_PATH;
  6155. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6156. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6157. ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
  6158. r = MsiRecordGetInteger(hrec, 2);
  6159. ok(r == 2, "Expected 2, got %d\n", r);
  6160. size = MAX_PATH;
  6161. r = MsiRecordGetStringA(hrec, 3, buf, &size);
  6162. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6163. ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
  6164. MsiCloseHandle(hrec);
  6165. r = MsiViewFetch(hview, &hrec);
  6166. ok(r == ERROR_NO_MORE_ITEMS,
  6167. "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6168. MsiViewClose(hview);
  6169. MsiCloseHandle(hview);
  6170. query = "DROP TABLE One";
  6171. r = run_query(hdb, 0, query);
  6172. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6173. query = "SELECT * FROM `One`";
  6174. r = do_query(hdb, query, &hrec);
  6175. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6176. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6177. query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
  6178. r = do_query(hdb, query, &hrec);
  6179. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6180. query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
  6181. r = do_query(hdb, query, &hrec);
  6182. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6183. MsiCloseHandle(hdb);
  6184. DeleteFileA(msifile);
  6185. }
  6186. static void test_dbmerge(void)
  6187. {
  6188. MSIHANDLE hdb, href, hview, hrec;
  6189. CHAR buf[MAX_PATH];
  6190. LPCSTR query;
  6191. DWORD size;
  6192. UINT r;
  6193. r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
  6194. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6195. r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
  6196. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6197. /* hDatabase is invalid */
  6198. r = MsiDatabaseMergeA(0, href, "MergeErrors");
  6199. ok(r == ERROR_INVALID_HANDLE,
  6200. "Expected ERROR_INVALID_HANDLE, got %d\n", r);
  6201. /* hDatabaseMerge is invalid */
  6202. r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
  6203. ok(r == ERROR_INVALID_HANDLE,
  6204. "Expected ERROR_INVALID_HANDLE, got %d\n", r);
  6205. /* szTableName is NULL */
  6206. r = MsiDatabaseMergeA(hdb, href, NULL);
  6207. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6208. /* szTableName is empty */
  6209. r = MsiDatabaseMergeA(hdb, href, "");
  6210. ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
  6211. /* both DBs empty, szTableName is valid */
  6212. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6213. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6214. query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
  6215. r = run_query(hdb, 0, query);
  6216. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6217. query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
  6218. r = run_query(href, 0, query);
  6219. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6220. /* column types don't match */
  6221. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6222. ok(r == ERROR_DATATYPE_MISMATCH,
  6223. "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
  6224. /* nothing in MergeErrors */
  6225. query = "SELECT * FROM `MergeErrors`";
  6226. r = do_query(hdb, query, &hrec);
  6227. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6228. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6229. query = "DROP TABLE `One`";
  6230. r = run_query(hdb, 0, query);
  6231. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6232. query = "DROP TABLE `One`";
  6233. r = run_query(href, 0, query);
  6234. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6235. query = "CREATE TABLE `One` ( "
  6236. "`A` CHAR(72), "
  6237. "`B` CHAR(56), "
  6238. "`C` CHAR(64) LOCALIZABLE, "
  6239. "`D` LONGCHAR, "
  6240. "`E` CHAR(72) NOT NULL, "
  6241. "`F` CHAR(56) NOT NULL, "
  6242. "`G` CHAR(64) NOT NULL LOCALIZABLE, "
  6243. "`H` LONGCHAR NOT NULL "
  6244. "PRIMARY KEY `A` )";
  6245. r = run_query(hdb, 0, query);
  6246. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6247. query = "CREATE TABLE `One` ( "
  6248. "`A` CHAR(64), "
  6249. "`B` CHAR(64), "
  6250. "`C` CHAR(64), "
  6251. "`D` CHAR(64), "
  6252. "`E` CHAR(64) NOT NULL, "
  6253. "`F` CHAR(64) NOT NULL, "
  6254. "`G` CHAR(64) NOT NULL, "
  6255. "`H` CHAR(64) NOT NULL "
  6256. "PRIMARY KEY `A` )";
  6257. r = run_query(href, 0, query);
  6258. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6259. /* column sting types don't match exactly */
  6260. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6261. ok(r == ERROR_SUCCESS,
  6262. "Expected ERROR_SUCCESS, got %d\n", r);
  6263. /* nothing in MergeErrors */
  6264. query = "SELECT * FROM `MergeErrors`";
  6265. r = do_query(hdb, query, &hrec);
  6266. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6267. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6268. query = "DROP TABLE `One`";
  6269. r = run_query(hdb, 0, query);
  6270. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6271. query = "DROP TABLE `One`";
  6272. r = run_query(href, 0, query);
  6273. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6274. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6275. r = run_query(hdb, 0, query);
  6276. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6277. query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
  6278. r = run_query(href, 0, query);
  6279. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6280. /* column names don't match */
  6281. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6282. ok(r == ERROR_DATATYPE_MISMATCH,
  6283. "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
  6284. /* nothing in MergeErrors */
  6285. query = "SELECT * FROM `MergeErrors`";
  6286. r = do_query(hdb, query, &hrec);
  6287. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6288. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6289. query = "DROP TABLE `One`";
  6290. r = run_query(hdb, 0, query);
  6291. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6292. query = "DROP TABLE `One`";
  6293. r = run_query(href, 0, query);
  6294. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6295. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6296. r = run_query(hdb, 0, query);
  6297. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6298. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
  6299. r = run_query(href, 0, query);
  6300. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6301. /* primary keys don't match */
  6302. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6303. ok(r == ERROR_DATATYPE_MISMATCH,
  6304. "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
  6305. /* nothing in MergeErrors */
  6306. query = "SELECT * FROM `MergeErrors`";
  6307. r = do_query(hdb, query, &hrec);
  6308. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6309. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6310. query = "DROP TABLE `One`";
  6311. r = run_query(hdb, 0, query);
  6312. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6313. query = "DROP TABLE `One`";
  6314. r = run_query(href, 0, query);
  6315. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6316. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6317. r = run_query(hdb, 0, query);
  6318. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6319. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
  6320. r = run_query(href, 0, query);
  6321. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6322. /* number of primary keys doesn't match */
  6323. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6324. ok(r == ERROR_DATATYPE_MISMATCH,
  6325. "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
  6326. /* nothing in MergeErrors */
  6327. query = "SELECT * FROM `MergeErrors`";
  6328. r = do_query(hdb, query, &hrec);
  6329. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6330. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6331. query = "DROP TABLE `One`";
  6332. r = run_query(hdb, 0, query);
  6333. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6334. query = "DROP TABLE `One`";
  6335. r = run_query(href, 0, query);
  6336. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6337. query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
  6338. r = run_query(hdb, 0, query);
  6339. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6340. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6341. r = run_query(href, 0, query);
  6342. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6343. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
  6344. r = run_query(href, 0, query);
  6345. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6346. /* number of columns doesn't match */
  6347. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6348. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6349. query = "SELECT * FROM `One`";
  6350. r = do_query(hdb, query, &hrec);
  6351. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6352. r = MsiRecordGetInteger(hrec, 1);
  6353. ok(r == 1, "Expected 1, got %d\n", r);
  6354. r = MsiRecordGetInteger(hrec, 2);
  6355. ok(r == 2, "Expected 2, got %d\n", r);
  6356. r = MsiRecordGetInteger(hrec, 3);
  6357. ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
  6358. MsiCloseHandle(hrec);
  6359. /* nothing in MergeErrors */
  6360. query = "SELECT * FROM `MergeErrors`";
  6361. r = do_query(hdb, query, &hrec);
  6362. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6363. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6364. query = "DROP TABLE `One`";
  6365. r = run_query(hdb, 0, query);
  6366. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6367. query = "DROP TABLE `One`";
  6368. r = run_query(href, 0, query);
  6369. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6370. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6371. r = run_query(hdb, 0, query);
  6372. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6373. query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
  6374. r = run_query(href, 0, query);
  6375. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6376. query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
  6377. r = run_query(href, 0, query);
  6378. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6379. /* number of columns doesn't match */
  6380. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6381. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6382. query = "SELECT * FROM `One`";
  6383. r = do_query(hdb, query, &hrec);
  6384. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6385. r = MsiRecordGetInteger(hrec, 1);
  6386. ok(r == 1, "Expected 1, got %d\n", r);
  6387. r = MsiRecordGetInteger(hrec, 2);
  6388. ok(r == 2, "Expected 2, got %d\n", r);
  6389. r = MsiRecordGetInteger(hrec, 3);
  6390. ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
  6391. MsiCloseHandle(hrec);
  6392. /* nothing in MergeErrors */
  6393. query = "SELECT * FROM `MergeErrors`";
  6394. r = do_query(hdb, query, &hrec);
  6395. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6396. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6397. query = "DROP TABLE `One`";
  6398. r = run_query(hdb, 0, query);
  6399. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6400. query = "DROP TABLE `One`";
  6401. r = run_query(href, 0, query);
  6402. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6403. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6404. r = run_query(hdb, 0, query);
  6405. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6406. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
  6407. r = run_query(hdb, 0, query);
  6408. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6409. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
  6410. r = run_query(hdb, 0, query);
  6411. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6412. query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
  6413. r = run_query(href, 0, query);
  6414. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6415. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
  6416. r = run_query(href, 0, query);
  6417. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6418. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
  6419. r = run_query(href, 0, query);
  6420. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6421. /* primary keys match, rows do not */
  6422. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6423. ok(r == ERROR_FUNCTION_FAILED,
  6424. "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  6425. /* nothing in MergeErrors */
  6426. query = "SELECT * FROM `MergeErrors`";
  6427. r = do_query(hdb, query, &hrec);
  6428. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6429. size = MAX_PATH;
  6430. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6431. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6432. ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
  6433. r = MsiRecordGetInteger(hrec, 2);
  6434. ok(r == 2, "Expected 2, got %d\n", r);
  6435. MsiCloseHandle(hrec);
  6436. r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
  6437. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6438. r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
  6439. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6440. size = MAX_PATH;
  6441. r = MsiRecordGetString(hrec, 1, buf, &size);
  6442. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6443. ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
  6444. size = MAX_PATH;
  6445. r = MsiRecordGetString(hrec, 2, buf, &size);
  6446. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6447. ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
  6448. "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
  6449. MsiCloseHandle(hrec);
  6450. r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
  6451. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6452. size = MAX_PATH;
  6453. r = MsiRecordGetString(hrec, 1, buf, &size);
  6454. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6455. ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
  6456. size = MAX_PATH;
  6457. r = MsiRecordGetString(hrec, 2, buf, &size);
  6458. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6459. ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
  6460. MsiCloseHandle(hrec);
  6461. MsiViewClose(hview);
  6462. MsiCloseHandle(hview);
  6463. query = "DROP TABLE `MergeErrors`";
  6464. r = run_query(hdb, 0, query);
  6465. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6466. query = "DROP TABLE `One`";
  6467. r = run_query(hdb, 0, query);
  6468. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6469. query = "DROP TABLE `One`";
  6470. r = run_query(href, 0, query);
  6471. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6472. query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
  6473. r = run_query(href, 0, query);
  6474. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6475. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
  6476. r = run_query(href, 0, query);
  6477. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6478. /* table from merged database is not in target database */
  6479. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6480. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6481. query = "SELECT * FROM `One`";
  6482. r = do_query(hdb, query, &hrec);
  6483. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6484. r = MsiRecordGetInteger(hrec, 1);
  6485. ok(r == 1, "Expected 1, got %d\n", r);
  6486. size = MAX_PATH;
  6487. r = MsiRecordGetStringA(hrec, 2, buf, &size);
  6488. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6489. ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
  6490. MsiCloseHandle(hrec);
  6491. /* nothing in MergeErrors */
  6492. query = "SELECT * FROM `MergeErrors`";
  6493. r = do_query(hdb, query, &hrec);
  6494. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6495. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6496. query = "DROP TABLE `One`";
  6497. r = run_query(hdb, 0, query);
  6498. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6499. query = "DROP TABLE `One`";
  6500. r = run_query(href, 0, query);
  6501. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6502. query = "CREATE TABLE `One` ( "
  6503. "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
  6504. r = run_query(hdb, 0, query);
  6505. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6506. query = "CREATE TABLE `One` ( "
  6507. "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
  6508. r = run_query(href, 0, query);
  6509. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6510. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
  6511. r = run_query(href, 0, query);
  6512. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6513. /* primary key is string */
  6514. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6515. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6516. query = "SELECT * FROM `One`";
  6517. r = do_query(hdb, query, &hrec);
  6518. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6519. size = MAX_PATH;
  6520. r = MsiRecordGetStringA(hrec, 1, buf, &size);
  6521. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6522. ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
  6523. r = MsiRecordGetInteger(hrec, 2);
  6524. ok(r == 1, "Expected 1, got %d\n", r);
  6525. MsiCloseHandle(hrec);
  6526. /* nothing in MergeErrors */
  6527. query = "SELECT * FROM `MergeErrors`";
  6528. r = do_query(hdb, query, &hrec);
  6529. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6530. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6531. create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
  6532. GetCurrentDirectoryA(MAX_PATH, buf);
  6533. r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
  6534. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6535. query = "DROP TABLE `One`";
  6536. r = run_query(hdb, 0, query);
  6537. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6538. query = "DROP TABLE `One`";
  6539. r = run_query(href, 0, query);
  6540. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6541. query = "CREATE TABLE `One` ( "
  6542. "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
  6543. r = run_query(hdb, 0, query);
  6544. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6545. query = "CREATE TABLE `One` ( "
  6546. "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
  6547. r = run_query(href, 0, query);
  6548. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6549. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
  6550. r = run_query(href, 0, query);
  6551. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6552. /* code page does not match */
  6553. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6554. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6555. query = "SELECT * FROM `One`";
  6556. r = do_query(hdb, query, &hrec);
  6557. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6558. r = MsiRecordGetInteger(hrec, 1);
  6559. ok(r == 1, "Expected 1, got %d\n", r);
  6560. size = MAX_PATH;
  6561. r = MsiRecordGetStringA(hrec, 2, buf, &size);
  6562. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6563. ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
  6564. MsiCloseHandle(hrec);
  6565. /* nothing in MergeErrors */
  6566. query = "SELECT * FROM `MergeErrors`";
  6567. r = do_query(hdb, query, &hrec);
  6568. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6569. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6570. query = "DROP TABLE `One`";
  6571. r = run_query(hdb, 0, query);
  6572. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6573. query = "DROP TABLE `One`";
  6574. r = run_query(href, 0, query);
  6575. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6576. query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
  6577. r = run_query(hdb, 0, query);
  6578. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6579. query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
  6580. r = run_query(href, 0, query);
  6581. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6582. create_file("binary.dat");
  6583. hrec = MsiCreateRecord(1);
  6584. MsiRecordSetStreamA(hrec, 1, "binary.dat");
  6585. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
  6586. r = run_query(href, hrec, query);
  6587. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6588. MsiCloseHandle(hrec);
  6589. /* binary data to merge */
  6590. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6591. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6592. query = "SELECT * FROM `One`";
  6593. r = do_query(hdb, query, &hrec);
  6594. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6595. r = MsiRecordGetInteger(hrec, 1);
  6596. ok(r == 1, "Expected 1, got %d\n", r);
  6597. size = MAX_PATH;
  6598. ZeroMemory(buf, MAX_PATH);
  6599. r = MsiRecordReadStream(hrec, 2, buf, &size);
  6600. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6601. ok(!lstrcmpA(buf, "binary.dat\n"),
  6602. "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
  6603. MsiCloseHandle(hrec);
  6604. /* nothing in MergeErrors */
  6605. query = "SELECT * FROM `MergeErrors`";
  6606. r = do_query(hdb, query, &hrec);
  6607. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6608. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6609. query = "DROP TABLE `One`";
  6610. r = run_query(hdb, 0, query);
  6611. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6612. query = "DROP TABLE `One`";
  6613. r = run_query(href, 0, query);
  6614. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6615. query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
  6616. r = run_query(hdb, 0, query);
  6617. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6618. r = run_query(href, 0, query);
  6619. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6620. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
  6621. r = run_query(href, 0, query);
  6622. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6623. query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
  6624. r = run_query(href, 0, query);
  6625. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6626. r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
  6627. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6628. query = "SELECT * FROM `One`";
  6629. r = MsiDatabaseOpenViewA(hdb, query, &hview);
  6630. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6631. r = MsiViewExecute(hview, 0);
  6632. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6633. r = MsiViewFetch(hview, &hrec);
  6634. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6635. r = MsiRecordGetInteger(hrec, 1);
  6636. ok(r == 1, "Expected 1, got %d\n", r);
  6637. size = MAX_PATH;
  6638. r = MsiRecordGetStringA(hrec, 2, buf, &size);
  6639. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6640. ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
  6641. MsiCloseHandle(hrec);
  6642. r = MsiViewFetch(hview, &hrec);
  6643. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6644. r = MsiRecordGetInteger(hrec, 1);
  6645. ok(r == 2, "Expected 2, got %d\n", r);
  6646. size = MAX_PATH;
  6647. r = MsiRecordGetStringA(hrec, 2, buf, &size);
  6648. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6649. ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
  6650. MsiCloseHandle(hrec);
  6651. r = MsiViewFetch(hview, &hrec);
  6652. ok(r == ERROR_NO_MORE_ITEMS,
  6653. "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6654. MsiViewClose(hview);
  6655. MsiCloseHandle(hview);
  6656. MsiCloseHandle(hdb);
  6657. MsiCloseHandle(href);
  6658. DeleteFileA(msifile);
  6659. DeleteFileA("refdb.msi");
  6660. DeleteFileA("codepage.idt");
  6661. DeleteFileA("binary.dat");
  6662. }
  6663. static void test_select_with_tablenames(void)
  6664. {
  6665. MSIHANDLE hdb, view, rec;
  6666. LPCSTR query;
  6667. UINT r;
  6668. int i;
  6669. int vals[4][2] = {
  6670. {1,12},
  6671. {4,12},
  6672. {1,15},
  6673. {4,15}};
  6674. hdb = create_db();
  6675. ok(hdb, "failed to create db\n");
  6676. /* Build a pair of tables with the same column names, but unique data */
  6677. query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
  6678. r = run_query(hdb, 0, query);
  6679. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6680. query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
  6681. r = run_query(hdb, 0, query);
  6682. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6683. query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
  6684. r = run_query(hdb, 0, query);
  6685. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6686. query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
  6687. r = run_query(hdb, 0, query);
  6688. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6689. query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
  6690. r = run_query(hdb, 0, query);
  6691. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6692. query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
  6693. r = run_query(hdb, 0, query);
  6694. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6695. /* Test that selection based on prefixing the column with the table
  6696. * actually selects the right data */
  6697. query = "SELECT T1.A, T2.B FROM T1,T2";
  6698. r = MsiDatabaseOpenView(hdb, query, &view);
  6699. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6700. r = MsiViewExecute(view, 0);
  6701. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6702. for (i = 0; i < 4; i++)
  6703. {
  6704. r = MsiViewFetch(view, &rec);
  6705. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6706. r = MsiRecordGetInteger(rec, 1);
  6707. ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
  6708. r = MsiRecordGetInteger(rec, 2);
  6709. ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
  6710. MsiCloseHandle(rec);
  6711. }
  6712. r = MsiViewFetch(view, &rec);
  6713. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6714. MsiViewClose(view);
  6715. MsiCloseHandle(view);
  6716. MsiCloseHandle(hdb);
  6717. DeleteFileA(msifile);
  6718. }
  6719. static const UINT ordervals[6][3] =
  6720. {
  6721. { MSI_NULL_INTEGER, 12, 13 },
  6722. { 1, 2, 3 },
  6723. { 6, 4, 5 },
  6724. { 8, 9, 7 },
  6725. { 10, 11, MSI_NULL_INTEGER },
  6726. { 14, MSI_NULL_INTEGER, 15 }
  6727. };
  6728. static void test_insertorder(void)
  6729. {
  6730. MSIHANDLE hdb, view, rec;
  6731. LPCSTR query;
  6732. UINT r;
  6733. int i;
  6734. hdb = create_db();
  6735. ok(hdb, "failed to create db\n");
  6736. query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
  6737. r = run_query(hdb, 0, query);
  6738. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6739. query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
  6740. r = run_query(hdb, 0, query);
  6741. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6742. query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
  6743. r = run_query(hdb, 0, query);
  6744. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6745. query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
  6746. r = run_query(hdb, 0, query);
  6747. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6748. query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
  6749. r = run_query(hdb, 0, query);
  6750. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6751. query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
  6752. r = run_query(hdb, 0, query);
  6753. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6754. /* fails because the primary key already
  6755. * has an MSI_NULL_INTEGER value set above
  6756. */
  6757. query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
  6758. r = run_query(hdb, 0, query);
  6759. ok(r == ERROR_FUNCTION_FAILED,
  6760. "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  6761. /* replicate the error where primary key is set twice */
  6762. query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
  6763. r = run_query(hdb, 0, query);
  6764. ok(r == ERROR_FUNCTION_FAILED,
  6765. "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
  6766. query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
  6767. r = run_query(hdb, 0, query);
  6768. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6769. query = "INSERT INTO `T` VALUES ( 16 )";
  6770. r = run_query(hdb, 0, query);
  6771. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6772. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6773. query = "INSERT INTO `T` VALUES ( 17, 18 )";
  6774. r = run_query(hdb, 0, query);
  6775. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6776. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6777. query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
  6778. r = run_query(hdb, 0, query);
  6779. ok(r == ERROR_BAD_QUERY_SYNTAX,
  6780. "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
  6781. query = "SELECT * FROM `T`";
  6782. r = MsiDatabaseOpenView(hdb, query, &view);
  6783. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6784. r = MsiViewExecute(view, 0);
  6785. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6786. for (i = 0; i < 6; i++)
  6787. {
  6788. r = MsiViewFetch(view, &rec);
  6789. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6790. r = MsiRecordGetInteger(rec, 1);
  6791. ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
  6792. r = MsiRecordGetInteger(rec, 2);
  6793. ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
  6794. r = MsiRecordGetInteger(rec, 3);
  6795. ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
  6796. MsiCloseHandle(rec);
  6797. }
  6798. r = MsiViewFetch(view, &rec);
  6799. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6800. MsiViewClose(view);
  6801. MsiCloseHandle(view);
  6802. query = "DELETE FROM `T` WHERE `A` IS NULL";
  6803. r = run_query(hdb, 0, query);
  6804. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6805. query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
  6806. r = run_query(hdb, 0, query);
  6807. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6808. query = "SELECT * FROM `T`";
  6809. r = MsiDatabaseOpenView(hdb, query, &view);
  6810. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6811. r = MsiViewExecute(view, 0);
  6812. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6813. for (i = 0; i < 6; i++)
  6814. {
  6815. r = MsiViewFetch(view, &rec);
  6816. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6817. r = MsiRecordGetInteger(rec, 1);
  6818. ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
  6819. r = MsiRecordGetInteger(rec, 2);
  6820. ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
  6821. r = MsiRecordGetInteger(rec, 3);
  6822. ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
  6823. MsiCloseHandle(rec);
  6824. }
  6825. r = MsiViewFetch(view, &rec);
  6826. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  6827. MsiViewClose(view);
  6828. MsiCloseHandle(view);
  6829. MsiCloseHandle(hdb);
  6830. DeleteFileA(msifile);
  6831. }
  6832. static void test_columnorder(void)
  6833. {
  6834. MSIHANDLE hdb, view, rec;
  6835. char buf[MAX_PATH];
  6836. LPCSTR query;
  6837. DWORD sz;
  6838. UINT r;
  6839. hdb = create_db();
  6840. ok(hdb, "failed to create db\n");
  6841. /* Each column is a slot:
  6842. * ---------------------
  6843. * | B | C | A | E | D |
  6844. * ---------------------
  6845. *
  6846. * When a column is selected as a primary key,
  6847. * the column occupying the nth primary key slot is swapped
  6848. * with the current position of the primary key in question:
  6849. *
  6850. * set primary key `D`
  6851. * --------------------- ---------------------
  6852. * | B | C | A | E | D | -> | D | C | A | E | B |
  6853. * --------------------- ---------------------
  6854. *
  6855. * set primary key `E`
  6856. * --------------------- ---------------------
  6857. * | D | C | A | E | B | -> | D | E | A | C | B |
  6858. * --------------------- ---------------------
  6859. */
  6860. query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
  6861. "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
  6862. "PRIMARY KEY `D`, `E`)";
  6863. r = run_query(hdb, 0, query);
  6864. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6865. query = "SELECT * FROM `T`";
  6866. r = MsiDatabaseOpenView(hdb, query, &view);
  6867. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6868. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  6869. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6870. sz = MAX_PATH;
  6871. lstrcpyA(buf, "kiwi");
  6872. r = MsiRecordGetString(rec, 1, buf, &sz);
  6873. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6874. ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
  6875. sz = MAX_PATH;
  6876. lstrcpyA(buf, "kiwi");
  6877. r = MsiRecordGetString(rec, 2, buf, &sz);
  6878. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6879. ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
  6880. sz = MAX_PATH;
  6881. lstrcpyA(buf, "kiwi");
  6882. r = MsiRecordGetString(rec, 3, buf, &sz);
  6883. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6884. ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
  6885. sz = MAX_PATH;
  6886. lstrcpyA(buf, "kiwi");
  6887. r = MsiRecordGetString(rec, 4, buf, &sz);
  6888. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6889. ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
  6890. sz = MAX_PATH;
  6891. lstrcpyA(buf, "kiwi");
  6892. r = MsiRecordGetString(rec, 5, buf, &sz);
  6893. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6894. ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
  6895. MsiCloseHandle(rec);
  6896. r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
  6897. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6898. sz = MAX_PATH;
  6899. lstrcpyA(buf, "kiwi");
  6900. r = MsiRecordGetString(rec, 1, buf, &sz);
  6901. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6902. ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
  6903. sz = MAX_PATH;
  6904. lstrcpyA(buf, "kiwi");
  6905. r = MsiRecordGetString(rec, 2, buf, &sz);
  6906. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6907. ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
  6908. sz = MAX_PATH;
  6909. lstrcpyA(buf, "kiwi");
  6910. r = MsiRecordGetString(rec, 3, buf, &sz);
  6911. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6912. ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
  6913. sz = MAX_PATH;
  6914. lstrcpyA(buf, "kiwi");
  6915. r = MsiRecordGetString(rec, 4, buf, &sz);
  6916. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6917. ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
  6918. sz = MAX_PATH;
  6919. lstrcpyA(buf, "kiwi");
  6920. r = MsiRecordGetString(rec, 5, buf, &sz);
  6921. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6922. ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
  6923. MsiCloseHandle(rec);
  6924. MsiViewClose(view);
  6925. MsiCloseHandle(view);
  6926. query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
  6927. "VALUES ( 1, 2, 'a', 3, 'bc' )";
  6928. r = run_query(hdb, 0, query);
  6929. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6930. query = "SELECT * FROM `T`";
  6931. r = do_query(hdb, query, &rec);
  6932. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6933. sz = MAX_PATH;
  6934. lstrcpyA(buf, "kiwi");
  6935. r = MsiRecordGetString(rec, 1, buf, &sz);
  6936. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6937. ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
  6938. r = MsiRecordGetInteger(rec, 2);
  6939. ok(r == 3, "Expected 3, got %d\n", r);
  6940. sz = MAX_PATH;
  6941. lstrcpyA(buf, "kiwi");
  6942. r = MsiRecordGetString(rec, 3, buf, &sz);
  6943. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6944. ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
  6945. r = MsiRecordGetInteger(rec, 4);
  6946. ok(r == 2, "Expected 2, got %d\n", r);
  6947. r = MsiRecordGetInteger(rec, 5);
  6948. ok(r == 1, "Expected 1, got %d\n", r);
  6949. MsiCloseHandle(rec);
  6950. query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
  6951. r = MsiDatabaseOpenView(hdb, query, &view);
  6952. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6953. r = MsiViewExecute(view, 0);
  6954. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6955. r = MsiViewFetch(view, &rec);
  6956. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6957. sz = MAX_PATH;
  6958. lstrcpyA(buf, "kiwi");
  6959. r = MsiRecordGetString(rec, 1, buf, &sz);
  6960. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6961. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  6962. r = MsiRecordGetInteger(rec, 2);
  6963. ok(r == 1, "Expected 1, got %d\n", r);
  6964. sz = MAX_PATH;
  6965. lstrcpyA(buf, "kiwi");
  6966. r = MsiRecordGetString(rec, 3, buf, &sz);
  6967. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6968. ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
  6969. MsiCloseHandle(rec);
  6970. r = MsiViewFetch(view, &rec);
  6971. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6972. sz = MAX_PATH;
  6973. lstrcpyA(buf, "kiwi");
  6974. r = MsiRecordGetString(rec, 1, buf, &sz);
  6975. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6976. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  6977. r = MsiRecordGetInteger(rec, 2);
  6978. ok(r == 2, "Expected 2, got %d\n", r);
  6979. sz = MAX_PATH;
  6980. lstrcpyA(buf, "kiwi");
  6981. r = MsiRecordGetString(rec, 3, buf, &sz);
  6982. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6983. ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
  6984. MsiCloseHandle(rec);
  6985. r = MsiViewFetch(view, &rec);
  6986. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6987. sz = MAX_PATH;
  6988. lstrcpyA(buf, "kiwi");
  6989. r = MsiRecordGetString(rec, 1, buf, &sz);
  6990. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6991. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  6992. r = MsiRecordGetInteger(rec, 2);
  6993. ok(r == 3, "Expected 3, got %d\n", r);
  6994. sz = MAX_PATH;
  6995. lstrcpyA(buf, "kiwi");
  6996. r = MsiRecordGetString(rec, 3, buf, &sz);
  6997. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  6998. ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
  6999. MsiCloseHandle(rec);
  7000. r = MsiViewFetch(view, &rec);
  7001. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7002. sz = MAX_PATH;
  7003. lstrcpyA(buf, "kiwi");
  7004. r = MsiRecordGetString(rec, 1, buf, &sz);
  7005. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7006. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7007. r = MsiRecordGetInteger(rec, 2);
  7008. ok(r == 4, "Expected 4, got %d\n", r);
  7009. sz = MAX_PATH;
  7010. lstrcpyA(buf, "kiwi");
  7011. r = MsiRecordGetString(rec, 3, buf, &sz);
  7012. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7013. ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
  7014. MsiCloseHandle(rec);
  7015. r = MsiViewFetch(view, &rec);
  7016. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7017. sz = MAX_PATH;
  7018. lstrcpyA(buf, "kiwi");
  7019. r = MsiRecordGetString(rec, 1, buf, &sz);
  7020. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7021. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7022. r = MsiRecordGetInteger(rec, 2);
  7023. ok(r == 5, "Expected 5, got %d\n", r);
  7024. sz = MAX_PATH;
  7025. lstrcpyA(buf, "kiwi");
  7026. r = MsiRecordGetString(rec, 3, buf, &sz);
  7027. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7028. ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
  7029. MsiCloseHandle(rec);
  7030. r = MsiViewFetch(view, &rec);
  7031. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  7032. MsiViewClose(view);
  7033. MsiCloseHandle(view);
  7034. query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
  7035. "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
  7036. "PRIMARY KEY `C`, `A`, `D`)";
  7037. r = run_query(hdb, 0, query);
  7038. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7039. query = "SELECT * FROM `Z`";
  7040. r = MsiDatabaseOpenView(hdb, query, &view);
  7041. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7042. r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
  7043. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7044. sz = MAX_PATH;
  7045. lstrcpyA(buf, "kiwi");
  7046. r = MsiRecordGetString(rec, 1, buf, &sz);
  7047. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7048. ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
  7049. sz = MAX_PATH;
  7050. lstrcpyA(buf, "kiwi");
  7051. r = MsiRecordGetString(rec, 2, buf, &sz);
  7052. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7053. ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
  7054. sz = MAX_PATH;
  7055. lstrcpyA(buf, "kiwi");
  7056. r = MsiRecordGetString(rec, 3, buf, &sz);
  7057. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7058. ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
  7059. sz = MAX_PATH;
  7060. lstrcpyA(buf, "kiwi");
  7061. r = MsiRecordGetString(rec, 4, buf, &sz);
  7062. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7063. ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
  7064. sz = MAX_PATH;
  7065. lstrcpyA(buf, "kiwi");
  7066. r = MsiRecordGetString(rec, 5, buf, &sz);
  7067. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7068. ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
  7069. MsiCloseHandle(rec);
  7070. r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
  7071. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7072. sz = MAX_PATH;
  7073. lstrcpyA(buf, "kiwi");
  7074. r = MsiRecordGetString(rec, 1, buf, &sz);
  7075. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7076. ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
  7077. sz = MAX_PATH;
  7078. lstrcpyA(buf, "kiwi");
  7079. r = MsiRecordGetString(rec, 2, buf, &sz);
  7080. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7081. ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
  7082. sz = MAX_PATH;
  7083. lstrcpyA(buf, "kiwi");
  7084. r = MsiRecordGetString(rec, 3, buf, &sz);
  7085. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7086. ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
  7087. sz = MAX_PATH;
  7088. lstrcpyA(buf, "kiwi");
  7089. r = MsiRecordGetString(rec, 4, buf, &sz);
  7090. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7091. ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
  7092. sz = MAX_PATH;
  7093. lstrcpyA(buf, "kiwi");
  7094. r = MsiRecordGetString(rec, 5, buf, &sz);
  7095. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7096. ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
  7097. MsiCloseHandle(rec);
  7098. MsiViewClose(view);
  7099. MsiCloseHandle(view);
  7100. query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
  7101. "VALUES ( 1, 2, 'a', 3, 'bc' )";
  7102. r = run_query(hdb, 0, query);
  7103. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7104. query = "SELECT * FROM `Z`";
  7105. r = do_query(hdb, query, &rec);
  7106. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7107. r = MsiRecordGetInteger(rec, 1);
  7108. ok(r == 2, "Expected 2, got %d\n", r);
  7109. sz = MAX_PATH;
  7110. lstrcpyA(buf, "kiwi");
  7111. r = MsiRecordGetString(rec, 2, buf, &sz);
  7112. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7113. ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
  7114. sz = MAX_PATH;
  7115. lstrcpyA(buf, "kiwi");
  7116. r = MsiRecordGetString(rec, 3, buf, &sz);
  7117. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7118. ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
  7119. r = MsiRecordGetInteger(rec, 4);
  7120. ok(r == 3, "Expected 3, got %d\n", r);
  7121. r = MsiRecordGetInteger(rec, 5);
  7122. ok(r == 1, "Expected 1, got %d\n", r);
  7123. MsiCloseHandle(rec);
  7124. query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
  7125. r = MsiDatabaseOpenView(hdb, query, &view);
  7126. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7127. r = MsiViewExecute(view, 0);
  7128. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7129. r = MsiViewFetch(view, &rec);
  7130. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7131. sz = MAX_PATH;
  7132. lstrcpyA(buf, "kiwi");
  7133. r = MsiRecordGetString(rec, 1, buf, &sz);
  7134. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7135. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7136. r = MsiRecordGetInteger(rec, 2);
  7137. ok(r == 1, "Expected 1, got %d\n", r);
  7138. sz = MAX_PATH;
  7139. lstrcpyA(buf, "kiwi");
  7140. r = MsiRecordGetString(rec, 3, buf, &sz);
  7141. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7142. ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
  7143. MsiCloseHandle(rec);
  7144. r = MsiViewFetch(view, &rec);
  7145. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7146. sz = MAX_PATH;
  7147. lstrcpyA(buf, "kiwi");
  7148. r = MsiRecordGetString(rec, 1, buf, &sz);
  7149. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7150. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7151. r = MsiRecordGetInteger(rec, 2);
  7152. ok(r == 2, "Expected 2, got %d\n", r);
  7153. sz = MAX_PATH;
  7154. lstrcpyA(buf, "kiwi");
  7155. r = MsiRecordGetString(rec, 3, buf, &sz);
  7156. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7157. ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
  7158. MsiCloseHandle(rec);
  7159. r = MsiViewFetch(view, &rec);
  7160. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7161. sz = MAX_PATH;
  7162. lstrcpyA(buf, "kiwi");
  7163. r = MsiRecordGetString(rec, 1, buf, &sz);
  7164. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7165. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7166. r = MsiRecordGetInteger(rec, 2);
  7167. ok(r == 3, "Expected 3, got %d\n", r);
  7168. sz = MAX_PATH;
  7169. lstrcpyA(buf, "kiwi");
  7170. r = MsiRecordGetString(rec, 3, buf, &sz);
  7171. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7172. ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
  7173. MsiCloseHandle(rec);
  7174. r = MsiViewFetch(view, &rec);
  7175. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7176. sz = MAX_PATH;
  7177. lstrcpyA(buf, "kiwi");
  7178. r = MsiRecordGetString(rec, 1, buf, &sz);
  7179. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7180. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7181. r = MsiRecordGetInteger(rec, 2);
  7182. ok(r == 4, "Expected 4, got %d\n", r);
  7183. sz = MAX_PATH;
  7184. lstrcpyA(buf, "kiwi");
  7185. r = MsiRecordGetString(rec, 3, buf, &sz);
  7186. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7187. ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
  7188. MsiCloseHandle(rec);
  7189. r = MsiViewFetch(view, &rec);
  7190. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7191. sz = MAX_PATH;
  7192. lstrcpyA(buf, "kiwi");
  7193. r = MsiRecordGetString(rec, 1, buf, &sz);
  7194. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7195. ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
  7196. r = MsiRecordGetInteger(rec, 2);
  7197. ok(r == 5, "Expected 5, got %d\n", r);
  7198. sz = MAX_PATH;
  7199. lstrcpyA(buf, "kiwi");
  7200. r = MsiRecordGetString(rec, 3, buf, &sz);
  7201. ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
  7202. ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
  7203. MsiCloseHandle(rec);
  7204. r = MsiViewFetch(view, &rec);
  7205. ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
  7206. MsiViewClose(view);
  7207. MsiCloseHandle(view);
  7208. MsiCloseHandle(hdb);
  7209. DeleteFileA(msifile);
  7210. }
  7211. static void test_createtable(void)
  7212. {
  7213. MSIHANDLE hdb, htab = 0, hrec = 0;
  7214. LPCSTR query;
  7215. UINT res;
  7216. DWORD size;
  7217. char buffer[0x20];
  7218. hdb = create_db();
  7219. ok(hdb, "failed to create db\n");
  7220. query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
  7221. res = MsiDatabaseOpenView( hdb, query, &htab );
  7222. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7223. if(res == ERROR_SUCCESS )
  7224. {
  7225. res = MsiViewExecute( htab, hrec );
  7226. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7227. res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
  7228. todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7229. size = sizeof(buffer);
  7230. res = MsiRecordGetString(hrec, 1, buffer, &size );
  7231. todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7232. MsiCloseHandle( hrec );
  7233. res = MsiViewClose( htab );
  7234. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7235. res = MsiCloseHandle( htab );
  7236. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7237. }
  7238. query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
  7239. res = MsiDatabaseOpenView( hdb, query, &htab );
  7240. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7241. if(res == ERROR_SUCCESS )
  7242. {
  7243. res = MsiViewExecute( htab, 0 );
  7244. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7245. res = MsiViewClose( htab );
  7246. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7247. res = MsiCloseHandle( htab );
  7248. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7249. query = "SELECT * FROM `a`";
  7250. res = MsiDatabaseOpenView( hdb, query, &htab );
  7251. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7252. res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
  7253. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7254. buffer[0] = 0;
  7255. size = sizeof(buffer);
  7256. res = MsiRecordGetString(hrec, 1, buffer, &size );
  7257. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7258. ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
  7259. MsiCloseHandle( hrec );
  7260. res = MsiViewClose( htab );
  7261. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7262. res = MsiCloseHandle( htab );
  7263. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7264. res = MsiDatabaseCommit(hdb);
  7265. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7266. res = MsiCloseHandle(hdb);
  7267. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7268. res = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
  7269. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7270. query = "SELECT * FROM `a`";
  7271. res = MsiDatabaseOpenView( hdb, query, &htab );
  7272. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7273. res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
  7274. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7275. buffer[0] = 0;
  7276. size = sizeof(buffer);
  7277. res = MsiRecordGetString(hrec, 1, buffer, &size );
  7278. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7279. ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
  7280. res = MsiCloseHandle( hrec );
  7281. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7282. res = MsiViewClose( htab );
  7283. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7284. res = MsiCloseHandle( htab );
  7285. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7286. }
  7287. res = MsiDatabaseCommit(hdb);
  7288. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7289. res = MsiCloseHandle(hdb);
  7290. ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
  7291. DeleteFileA(msifile);
  7292. }
  7293. static void test_embedded_nulls(void)
  7294. {
  7295. static const char control_table[] =
  7296. "Dialog\tText\n"
  7297. "s72\tL0\n"
  7298. "Control\tDialog\n"
  7299. "LicenseAgreementDlg\ttext\x11\x19text\0text";
  7300. UINT r, sz;
  7301. MSIHANDLE hdb, hrec;
  7302. char buffer[32];
  7303. r = MsiOpenDatabaseA( msifile, MSIDBOPEN_CREATE, &hdb );
  7304. ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
  7305. GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
  7306. write_file( "temp_file", control_table, sizeof(control_table) );
  7307. r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
  7308. ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
  7309. DeleteFileA( "temp_file" );
  7310. r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
  7311. ok( r == ERROR_SUCCESS, "query failed %u\n", r );
  7312. buffer[0] = 0;
  7313. sz = sizeof(buffer);
  7314. r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
  7315. ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
  7316. ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
  7317. MsiCloseHandle( hrec );
  7318. MsiCloseHandle( hdb );
  7319. DeleteFileA( msifile );
  7320. }
  7321. static void test_select_column_names(void)
  7322. {
  7323. MSIHANDLE hdb = 0, rec, rec2, view;
  7324. char buffer[32];
  7325. UINT r, size;
  7326. DeleteFile(msifile);
  7327. r = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
  7328. ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r );
  7329. r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)");
  7330. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7331. r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" );
  7332. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7333. r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
  7334. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7335. r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
  7336. todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
  7337. r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
  7338. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7339. r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" );
  7340. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7341. r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" );
  7342. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7343. r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" );
  7344. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7345. r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" );
  7346. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7347. r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" );
  7348. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7349. r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" );
  7350. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7351. r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" );
  7352. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7353. r = MsiDatabaseOpenView( hdb, "SELECT '' FROM `t`", &view );
  7354. ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
  7355. r = MsiViewExecute( view, 0 );
  7356. ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
  7357. r = MsiViewFetch( view, &rec );
  7358. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7359. r = MsiRecordGetFieldCount( rec );
  7360. ok( r == 1, "got %u\n", r );
  7361. r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec2 );
  7362. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7363. r = MsiRecordGetFieldCount( rec2 );
  7364. ok( r == 1, "got %u\n", r );
  7365. size = sizeof(buffer);
  7366. memset( buffer, 0x55, sizeof(buffer) );
  7367. r = MsiRecordGetStringA( rec2, 1, buffer, &size );
  7368. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7369. ok( !buffer[0], "got \"%s\"\n", buffer );
  7370. MsiCloseHandle( rec2 );
  7371. r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec2 );
  7372. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7373. r = MsiRecordGetFieldCount( rec2 );
  7374. ok( r == 1, "got %u\n", r );
  7375. size = sizeof(buffer);
  7376. memset( buffer, 0x55, sizeof(buffer) );
  7377. r = MsiRecordGetStringA( rec2, 1, buffer, &size );
  7378. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7379. ok( !lstrcmpA( buffer, "f0" ), "got \"%s\"\n", buffer );
  7380. MsiCloseHandle( rec2 );
  7381. size = sizeof(buffer);
  7382. memset( buffer, 0x55, sizeof(buffer) );
  7383. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7384. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7385. ok( !buffer[0], "got \"%s\"\n", buffer );
  7386. MsiCloseHandle( rec );
  7387. r = MsiViewFetch( view, &rec );
  7388. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7389. size = sizeof(buffer);
  7390. memset( buffer, 0x55, sizeof(buffer) );
  7391. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7392. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7393. ok( !buffer[0], "got \"%s\"\n", buffer );
  7394. MsiCloseHandle( rec );
  7395. r = MsiViewFetch( view, &rec );
  7396. ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
  7397. MsiCloseHandle( rec );
  7398. MsiViewClose( view );
  7399. MsiCloseHandle( view );
  7400. r = MsiDatabaseOpenView( hdb, "SELECT `a`, '' FROM `t`", &view );
  7401. ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
  7402. r = MsiViewExecute( view, 0 );
  7403. ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
  7404. r = MsiViewFetch( view, &rec );
  7405. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7406. r = MsiRecordGetFieldCount( rec );
  7407. ok( r == 2, "got %u\n", r );
  7408. size = sizeof(buffer);
  7409. memset( buffer, 0x55, sizeof(buffer) );
  7410. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7411. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7412. ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
  7413. MsiCloseHandle( rec );
  7414. r = MsiViewFetch( view, &rec );
  7415. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7416. size = sizeof(buffer);
  7417. memset( buffer, 0x55, sizeof(buffer) );
  7418. r = MsiRecordGetStringA( rec, 2, buffer, &size );
  7419. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7420. ok( !buffer[0], "got \"%s\"\n", buffer );
  7421. MsiCloseHandle( rec );
  7422. r = MsiViewFetch( view, &rec );
  7423. ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
  7424. MsiCloseHandle( rec );
  7425. MsiViewClose( view );
  7426. MsiCloseHandle( view );
  7427. r = MsiDatabaseOpenView( hdb, "SELECT '', `a` FROM `t`", &view );
  7428. ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
  7429. r = MsiViewExecute( view, 0 );
  7430. ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
  7431. r = MsiViewFetch( view, &rec );
  7432. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7433. r = MsiRecordGetFieldCount( rec );
  7434. ok( r == 2, "got %u\n", r );
  7435. size = sizeof(buffer);
  7436. memset( buffer, 0x55, sizeof(buffer) );
  7437. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7438. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7439. ok( !buffer[0], "got \"%s\"\n", buffer );
  7440. size = sizeof(buffer);
  7441. memset( buffer, 0x55, sizeof(buffer) );
  7442. r = MsiRecordGetStringA( rec, 2, buffer, &size );
  7443. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7444. ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
  7445. MsiCloseHandle( rec );
  7446. r = MsiViewFetch( view, &rec );
  7447. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7448. size = sizeof(buffer);
  7449. memset( buffer, 0x55, sizeof(buffer) );
  7450. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7451. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7452. ok( !buffer[0], "got \"%s\"\n", buffer );
  7453. size = sizeof(buffer);
  7454. memset( buffer, 0x55, sizeof(buffer) );
  7455. r = MsiRecordGetStringA( rec, 2, buffer, &size );
  7456. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7457. ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
  7458. MsiCloseHandle( rec );
  7459. r = MsiViewFetch( view, &rec );
  7460. ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
  7461. MsiCloseHandle( rec );
  7462. MsiViewClose( view );
  7463. MsiCloseHandle( view );
  7464. r = MsiDatabaseOpenView( hdb, "SELECT `a`, '', `b` FROM `t`", &view );
  7465. ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
  7466. r = MsiViewExecute( view, 0 );
  7467. ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
  7468. r = MsiViewFetch( view, &rec );
  7469. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7470. r = MsiRecordGetFieldCount( rec );
  7471. ok( r == 3, "got %u\n", r );
  7472. size = sizeof(buffer);
  7473. memset( buffer, 0x55, sizeof(buffer) );
  7474. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7475. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7476. ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
  7477. size = sizeof(buffer);
  7478. memset( buffer, 0x55, sizeof(buffer) );
  7479. r = MsiRecordGetStringA( rec, 2, buffer, &size );
  7480. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7481. ok( !buffer[0], "got \"%s\"\n", buffer );
  7482. size = sizeof(buffer);
  7483. memset( buffer, 0x55, sizeof(buffer) );
  7484. r = MsiRecordGetStringA( rec, 3, buffer, &size );
  7485. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7486. ok( !lstrcmpA( buffer, "2" ), "got \"%s\"\n", buffer );
  7487. MsiCloseHandle( rec );
  7488. r = MsiViewFetch( view, &rec );
  7489. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7490. size = sizeof(buffer);
  7491. memset( buffer, 0x55, sizeof(buffer) );
  7492. r = MsiRecordGetStringA( rec, 1, buffer, &size );
  7493. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7494. ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
  7495. size = sizeof(buffer);
  7496. memset( buffer, 0x55, sizeof(buffer) );
  7497. r = MsiRecordGetStringA( rec, 2, buffer, &size );
  7498. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7499. ok( !buffer[0], "got \"%s\"\n", buffer );
  7500. size = sizeof(buffer);
  7501. memset( buffer, 0x55, sizeof(buffer) );
  7502. r = MsiRecordGetStringA( rec, 3, buffer, &size );
  7503. ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
  7504. ok( !lstrcmpA( buffer, "4" ), "got \"%s\"\n", buffer );
  7505. MsiCloseHandle( rec );
  7506. r = MsiViewFetch( view, &rec );
  7507. ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
  7508. MsiCloseHandle( rec );
  7509. MsiViewClose( view );
  7510. MsiCloseHandle( view );
  7511. r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" );
  7512. ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
  7513. r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" );
  7514. todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7515. r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" );
  7516. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7517. r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" );
  7518. ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7519. r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" );
  7520. todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
  7521. r = MsiCloseHandle( hdb );
  7522. ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r);
  7523. }
  7524. START_TEST(db)
  7525. {
  7526. test_msidatabase();
  7527. test_msiinsert();
  7528. test_msidecomposedesc();
  7529. test_msibadqueries();
  7530. test_viewmodify();
  7531. test_viewgetcolumninfo();
  7532. test_getcolinfo();
  7533. test_msiexport();
  7534. test_longstrings();
  7535. test_streamtable();
  7536. test_binary();
  7537. test_where_not_in_selected();
  7538. test_where();
  7539. test_msiimport();
  7540. test_binary_import();
  7541. test_markers();
  7542. test_handle_limit();
  7543. test_try_transform();
  7544. test_join();
  7545. test_temporary_table();
  7546. test_alter();
  7547. test_integers();
  7548. test_update();
  7549. test_special_tables();
  7550. test_tables_order();
  7551. test_rows_order();
  7552. test_select_markers();
  7553. test_viewmodify_update();
  7554. test_viewmodify_assign();
  7555. test_stringtable();
  7556. test_viewmodify_delete();
  7557. test_defaultdatabase();
  7558. test_order();
  7559. test_viewmodify_delete_temporary();
  7560. test_deleterow();
  7561. test_quotes();
  7562. test_carriagereturn();
  7563. test_noquotes();
  7564. test_forcecodepage();
  7565. test_viewmodify_refresh();
  7566. test_where_viewmodify();
  7567. test_storages_table();
  7568. test_dbtopackage();
  7569. test_droptable();
  7570. test_dbmerge();
  7571. test_select_with_tablenames();
  7572. test_insertorder();
  7573. test_columnorder();
  7574. test_suminfo_import();
  7575. test_createtable();
  7576. test_collation();
  7577. test_embedded_nulls();
  7578. test_select_column_names();
  7579. }