hlink/tests: Add a trailing '\n' to an ok() call.
[wine] / dlls / msi / tests / db.c
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
21 #define COBJMACROS
22
23 #include <stdio.h>
24
25 #include <windows.h>
26 #include <msi.h>
27 #include <msidefs.h>
28 #include <msiquery.h>
29
30 #include <objidl.h>
31
32 #include "wine/test.h"
33
34 static const char *msifile = "winetest-db.msi";
35 static const char *msifile2 = "winetst2-db.msi";
36 static const char *mstfile = "winetst-db.mst";
37 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','-','d','b','.','m','s','i',0};
38
39 static void test_msidatabase(void)
40 {
41     MSIHANDLE hdb = 0, hdb2 = 0;
42     UINT res;
43
44     DeleteFile(msifile);
45
46     res = MsiOpenDatabase( msifile, msifile2, &hdb );
47     ok( res == ERROR_OPEN_FAILED, "expected failure\n");
48
49     res = MsiOpenDatabase( msifile, (LPSTR) 0xff, &hdb );
50     ok( res == ERROR_INVALID_PARAMETER, "expected failure\n");
51
52     res = MsiCloseHandle( hdb );
53     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
54
55     /* create an empty database */
56     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
57     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
58
59     res = MsiDatabaseCommit( hdb );
60     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
61
62     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
63
64     res = MsiCloseHandle( hdb );
65     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
66     res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
67     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
68
69     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile2 ), "database should exist\n");
70
71     res = MsiDatabaseCommit( hdb2 );
72     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
73
74     res = MsiCloseHandle( hdb2 );
75     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
76
77     res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
78     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
79
80     res = MsiCloseHandle( hdb2 );
81     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
82
83     ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile2 ), "uncommitted database should not exist\n");
84
85     res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
86     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
87
88     res = MsiDatabaseCommit( hdb2 );
89     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
90
91     res = MsiCloseHandle( hdb2 );
92     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
93
94     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile2 ), "committed database should exist\n");
95
96     res = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
97     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
98
99     res = MsiCloseHandle( hdb );
100     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
101
102     res = MsiOpenDatabase( msifile, MSIDBOPEN_DIRECT, &hdb );
103     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
104
105     res = MsiCloseHandle( hdb );
106     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
107
108     res = MsiOpenDatabase( msifile, MSIDBOPEN_TRANSACT, &hdb );
109     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
110
111     res = MsiCloseHandle( hdb );
112     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
113     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
114
115     /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
116     res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
117     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
118
119     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
120
121     res = MsiCloseHandle( hdb );
122     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
123
124     ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile ), "database should exist\n");
125
126     res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
127     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
128
129     res = MsiDatabaseCommit( hdb );
130     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
131
132     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
133
134     res = MsiCloseHandle( hdb );
135     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
136
137     res = DeleteFile( msifile2 );
138     ok( res == TRUE, "Failed to delete database\n" );
139
140     res = DeleteFile( msifile );
141     ok( res == TRUE, "Failed to delete database\n" );
142 }
143
144 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
145 {
146     MSIHANDLE hview = 0;
147     UINT r, ret;
148
149     if (phrec)
150         *phrec = 0;
151
152     /* open a select query */
153     r = MsiDatabaseOpenView(hdb, query, &hview);
154     if (r != ERROR_SUCCESS)
155         return r;
156     r = MsiViewExecute(hview, 0);
157     if (r != ERROR_SUCCESS)
158         return r;
159     ret = MsiViewFetch(hview, phrec);
160     r = MsiViewClose(hview);
161     if (r != ERROR_SUCCESS)
162         return r;
163     r = MsiCloseHandle(hview);
164     if (r != ERROR_SUCCESS)
165         return r;
166     return ret;
167 }
168
169 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
170 {
171     MSIHANDLE hview = 0;
172     UINT r;
173
174     r = MsiDatabaseOpenView(hdb, query, &hview);
175     if( r != ERROR_SUCCESS )
176         return r;
177
178     r = MsiViewExecute(hview, hrec);
179     if( r == ERROR_SUCCESS )
180         r = MsiViewClose(hview);
181     MsiCloseHandle(hview);
182     return r;
183 }
184
185 static UINT create_component_table( MSIHANDLE hdb )
186 {
187     return run_query( hdb, 0,
188             "CREATE TABLE `Component` ( "
189             "`Component` CHAR(72) NOT NULL, "
190             "`ComponentId` CHAR(38), "
191             "`Directory_` CHAR(72) NOT NULL, "
192             "`Attributes` SHORT NOT NULL, "
193             "`Condition` CHAR(255), "
194             "`KeyPath` CHAR(72) "
195             "PRIMARY KEY `Component`)" );
196 }
197
198 static UINT create_custom_action_table( MSIHANDLE hdb )
199 {
200     return run_query( hdb, 0,
201             "CREATE TABLE `CustomAction` ( "
202             "`Action` CHAR(72) NOT NULL, "
203             "`Type` SHORT NOT NULL, "
204             "`Source` CHAR(72), "
205             "`Target` CHAR(255) "
206             "PRIMARY KEY `Action`)" );
207 }
208
209 static UINT create_directory_table( MSIHANDLE hdb )
210 {
211     return run_query( hdb, 0,
212             "CREATE TABLE `Directory` ( "
213             "`Directory` CHAR(255) NOT NULL, "
214             "`Directory_Parent` CHAR(255), "
215             "`DefaultDir` CHAR(255) NOT NULL "
216             "PRIMARY KEY `Directory`)" );
217 }
218
219 static UINT create_feature_components_table( MSIHANDLE hdb )
220 {
221     return run_query( hdb, 0,
222             "CREATE TABLE `FeatureComponents` ( "
223             "`Feature_` CHAR(38) NOT NULL, "
224             "`Component_` CHAR(72) NOT NULL "
225             "PRIMARY KEY `Feature_`, `Component_` )" );
226 }
227
228 static UINT create_std_dlls_table( MSIHANDLE hdb )
229 {
230     return run_query( hdb, 0,
231             "CREATE TABLE `StdDlls` ( "
232             "`File` CHAR(255) NOT NULL, "
233             "`Binary_` CHAR(72) NOT NULL "
234             "PRIMARY KEY `File` )" );
235 }
236
237 static UINT create_binary_table( MSIHANDLE hdb )
238 {
239     return run_query( hdb, 0,
240             "CREATE TABLE `Binary` ( "
241             "`Name` CHAR(72) NOT NULL, "
242             "`Data` CHAR(72) NOT NULL "
243             "PRIMARY KEY `Name` )" );
244 }
245
246 #define make_add_entry(type, qtext) \
247     static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
248     { \
249         char insert[] = qtext; \
250         char *query; \
251         UINT sz, r; \
252         sz = strlen(values) + sizeof insert; \
253         query = HeapAlloc(GetProcessHeap(),0,sz); \
254         sprintf(query,insert,values); \
255         r = run_query( hdb, 0, query ); \
256         HeapFree(GetProcessHeap(), 0, query); \
257         return r; \
258     }
259
260 make_add_entry(component,
261                "INSERT INTO `Component`  "
262                "(`Component`, `ComponentId`, `Directory_`, "
263                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
264
265 make_add_entry(custom_action,
266                "INSERT INTO `CustomAction`  "
267                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
268
269 make_add_entry(feature_components,
270                "INSERT INTO `FeatureComponents` "
271                "(`Feature_`, `Component_`) VALUES( %s )")
272
273 make_add_entry(std_dlls,
274                "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
275
276 make_add_entry(binary,
277                "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
278
279 static void test_msiinsert(void)
280 {
281     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
282     UINT r;
283     const char *query;
284     char buf[80];
285     DWORD sz;
286
287     DeleteFile(msifile);
288
289     /* just MsiOpenDatabase should not create a file */
290     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
291     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
292
293     /* create a table */
294     query = "CREATE TABLE `phone` ( "
295             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
296             "PRIMARY KEY `id`)";
297     r = MsiDatabaseOpenView(hdb, query, &hview);
298     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
299     r = MsiViewExecute(hview, 0);
300     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
301     r = MsiViewClose(hview);
302     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
303     r = MsiCloseHandle(hview);
304     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
305
306     /* insert a value into it */
307     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
308         "VALUES('1', 'Abe', '8675309')";
309     r = MsiDatabaseOpenView(hdb, query, &hview);
310     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
311     r = MsiViewExecute(hview, 0);
312     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
313     r = MsiViewClose(hview);
314     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
315     r = MsiCloseHandle(hview);
316     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
317
318     query = "SELECT * FROM `phone` WHERE `id` = 1";
319     r = do_query(hdb, query, &hrec);
320     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
321
322     /* check the record contains what we put in it */
323     r = MsiRecordGetFieldCount(hrec);
324     ok(r == 3, "record count wrong\n");
325
326     r = MsiRecordIsNull(hrec, 0);
327     ok(r == FALSE, "field 0 not null\n");
328
329     r = MsiRecordGetInteger(hrec, 1);
330     ok(r == 1, "field 1 contents wrong\n");
331     sz = sizeof buf;
332     r = MsiRecordGetString(hrec, 2, buf, &sz);
333     ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
334     ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
335     sz = sizeof buf;
336     r = MsiRecordGetString(hrec, 3, buf, &sz);
337     ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
338     ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
339
340     r = MsiCloseHandle(hrec);
341     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
342
343     /* open a select query */
344     hrec = 100;
345     query = "SELECT * FROM `phone` WHERE `id` >= 10";
346     r = do_query(hdb, query, &hrec);
347     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
348     ok(hrec == 0, "hrec should be null\n");
349
350     r = MsiCloseHandle(hrec);
351     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
352
353     query = "SELECT * FROM `phone` WHERE `id` < 0";
354     r = do_query(hdb, query, &hrec);
355     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
356
357     query = "SELECT * FROM `phone` WHERE `id` <= 0";
358     r = do_query(hdb, query, &hrec);
359     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
360
361     query = "SELECT * FROM `phone` WHERE `id` <> 1";
362     r = do_query(hdb, query, &hrec);
363     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
364
365     query = "SELECT * FROM `phone` WHERE `id` > 10";
366     r = do_query(hdb, query, &hrec);
367     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
368
369     /* now try a few bad INSERT xqueries */
370     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
371         "VALUES(?, ?)";
372     r = MsiDatabaseOpenView(hdb, query, &hview);
373     ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
374
375     /* construct a record to insert */
376     hrec = MsiCreateRecord(4);
377     r = MsiRecordSetInteger(hrec, 1, 2);
378     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
379     r = MsiRecordSetString(hrec, 2, "Adam");
380     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
381     r = MsiRecordSetString(hrec, 3, "96905305");
382     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
383
384     /* insert another value, using a record and wildcards */
385     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
386         "VALUES(?, ?, ?)";
387     r = MsiDatabaseOpenView(hdb, query, &hview);
388     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
389
390     if (r == ERROR_SUCCESS)
391     {
392         r = MsiViewExecute(hview, hrec);
393         ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
394         r = MsiViewClose(hview);
395         ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
396         r = MsiCloseHandle(hview);
397         ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
398     }
399     r = MsiCloseHandle(hrec);
400     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
401
402     r = MsiViewFetch(0, NULL);
403     ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
404
405     r = MsiDatabaseCommit(hdb);
406     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
407
408     r = MsiCloseHandle(hdb);
409     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
410
411     r = DeleteFile(msifile);
412     ok(r == TRUE, "file didn't exist after commit\n");
413 }
414
415 typedef UINT (WINAPI *fnMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
416 static fnMsiDecomposeDescriptorA pMsiDecomposeDescriptorA;
417
418 static void test_msidecomposedesc(void)
419 {
420     char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
421     const char *desc;
422     UINT r;
423     DWORD len;
424     HMODULE hmod;
425
426     hmod = GetModuleHandle("msi.dll");
427     pMsiDecomposeDescriptorA = (fnMsiDecomposeDescriptorA)
428         GetProcAddress(hmod, "MsiDecomposeDescriptorA");
429     if (!pMsiDecomposeDescriptorA)
430         return;
431
432     /* test a valid feature descriptor */
433     desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
434     len = 0;
435     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
436     ok(r == ERROR_SUCCESS, "returned an error\n");
437     ok(len == strlen(desc), "length was wrong\n");
438     ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
439     ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
440     ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
441
442     /* test an invalid feature descriptor with too many characters */
443     desc = "']gAVn-}f(ZXfeAR6.ji"
444            "ThisWillFailIfTheresMoreThanAGuidsChars>"
445            "3w2x^IGfe?CxI5heAvk.";
446     len = 0;
447     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
448     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
449
450     /*
451      * Test a valid feature descriptor with the
452      * maximum number of characters and some trailing characters.
453      */
454     desc = "']gAVn-}f(ZXfeAR6.ji"
455            "ThisWillWorkIfTheresLTEThanAGuidsChars>"
456            "3w2x^IGfe?CxI5heAvk."
457            "extra";
458     len = 0;
459     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
460     ok(r == ERROR_SUCCESS, "returned wrong error\n");
461     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
462
463     len = 0;
464     r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
465     ok(r == ERROR_SUCCESS, "returned wrong error\n");
466     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
467
468     len = 0;
469     r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
470     ok(r == ERROR_SUCCESS, "returned wrong error\n");
471     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
472
473     len = 0;
474     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
475     ok(r == ERROR_SUCCESS, "returned wrong error\n");
476     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
477
478     len = 0;
479     r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
480     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
481     ok(len == 0, "length wrong\n");
482 }
483
484 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
485 {
486     MSIHANDLE htab = 0;
487     UINT res;
488
489     res = MsiDatabaseOpenView( hdb, szQuery, &htab );
490     if(res == ERROR_SUCCESS )
491     {
492         UINT r;
493
494         r = MsiViewExecute( htab, hrec );
495         if(r != ERROR_SUCCESS )
496             res = r;
497
498         r = MsiViewClose( htab );
499         if(r != ERROR_SUCCESS )
500             res = r;
501
502         r = MsiCloseHandle( htab );
503         if(r != ERROR_SUCCESS )
504             res = r;
505     }
506     return res;
507 }
508
509 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
510 {
511     return try_query_param( hdb, szQuery, 0 );
512 }
513
514 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
515 {
516     MSIHANDLE hrec = 0;
517     UINT r;
518
519     hrec = MsiCreateRecord( 1 );
520     MsiRecordSetString( hrec, 1, "Hello");
521
522     r = try_query_param( hdb, szQuery, hrec );
523
524     MsiCloseHandle( hrec );
525     return r;
526 }
527
528 static void test_msibadqueries(void)
529 {
530     MSIHANDLE hdb = 0;
531     UINT r;
532
533     DeleteFile(msifile);
534
535     /* just MsiOpenDatabase should not create a file */
536     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
537     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
538
539     r = MsiDatabaseCommit( hdb );
540     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
541
542     r = MsiCloseHandle( hdb );
543     ok(r == ERROR_SUCCESS , "Failed to close database\n");
544
545     /* open it readonly */
546     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb );
547     ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
548
549     /* add a table to it */
550     r = try_query( hdb, "select * from _Tables");
551     ok(r == ERROR_SUCCESS , "query 1 failed\n");
552
553     r = MsiCloseHandle( hdb );
554     ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
555
556     /* open it read/write */
557     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
558     ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
559
560     /* a bunch of test queries that fail with the native MSI */
561
562     r = try_query( hdb, "CREATE TABLE");
563     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
564
565     r = try_query( hdb, "CREATE TABLE `a`");
566     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
567
568     r = try_query( hdb, "CREATE TABLE `a` ()");
569     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
570
571     r = try_query( hdb, "CREATE TABLE `a` (`b`)");
572     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
573
574     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
575     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
576
577     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
578     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
579
580     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
581     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
582
583     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
584     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
585
586     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
587     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
588
589     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
590     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
591
592     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
593     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
594
595     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
596     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
597
598     r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
599     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
600
601     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
602     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
603
604     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
605     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
606
607     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
608     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
609
610     r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
611     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
612
613     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
614     ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
615
616     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
617     ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
618
619     r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
620           "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
621     ok(r == ERROR_SUCCESS , "query 4 failed\n");
622
623     r = MsiDatabaseCommit( hdb );
624     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
625
626     r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
627                           "PRIMARY KEY `foo`)");
628     ok(r == ERROR_SUCCESS , "query 4 failed\n");
629
630     r = try_insert_query( hdb, "insert into a  ( `b` ) VALUES ( ? )");
631     ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
632
633     r = MsiDatabaseCommit( hdb );
634     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
635
636     r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
637                           "PRIMARY KEY `ba`)");
638     ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
639
640     r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
641     ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
642
643     r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
644                           "PRIMARY KEY `t`)");
645     ok(r == ERROR_SUCCESS , "query 7 failed\n");
646
647     r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
648     ok(r == ERROR_SUCCESS , "query 8 failed\n");
649
650     r = try_query( hdb, "select * from c");
651     ok(r == ERROR_SUCCESS , "query failed\n");
652
653     r = try_query( hdb, "select * from c where b = 'x");
654     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
655
656     r = try_query( hdb, "select * from c where b = 'x'");
657     ok(r == ERROR_SUCCESS, "query failed\n");
658
659     r = try_query( hdb, "select * from 'c'");
660     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
661
662     r = try_query( hdb, "select * from ''");
663     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
664
665     r = try_query( hdb, "select * from c where b = x");
666     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
667
668     r = try_query( hdb, "select * from c where b = \"x\"");
669     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
670
671     r = try_query( hdb, "select * from c where b = 'x'");
672     ok(r == ERROR_SUCCESS, "query failed\n");
673
674     r = try_query( hdb, "select * from c where b = '\"x'");
675     ok(r == ERROR_SUCCESS, "query failed\n");
676
677     if (0)  /* FIXME: this query causes trouble with other tests */
678     {
679         r = try_query( hdb, "select * from c where b = '\\\'x'");
680         ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
681     }
682
683     r = try_query( hdb, "select * from 'c'");
684     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
685
686     r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
687     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
688
689     r = try_query( hdb, "SELECT * FROM \5a" );
690     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
691
692     r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
693     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
694
695     r = try_query( hdb, "SELECT * FROM a\5" );
696     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
697
698     r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
699     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
700
701     r = try_query( hdb, "SELECT * FROM -a" );
702     todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
703
704     r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
705     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
706
707     r = try_query( hdb, "SELECT * FROM a-" );
708     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
709
710     r = MsiCloseHandle( hdb );
711     ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
712
713     r = DeleteFile( msifile );
714     ok(r == TRUE, "file didn't exist after commit\n");
715 }
716
717 static void test_viewmodify(void)
718 {
719     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
720     UINT r;
721     MSIDBERROR err;
722     const char *query;
723     char buffer[0x100];
724     DWORD sz;
725
726     DeleteFile(msifile);
727
728     /* just MsiOpenDatabase should not create a file */
729     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
730     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
731
732     query = "CREATE TABLE `phone` ( "
733             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
734             "PRIMARY KEY `id`)";
735     r = run_query( hdb, 0, query );
736     ok(r == ERROR_SUCCESS, "query failed\n");
737
738     /* check what the error function reports without doing anything */
739     sz = 0;
740     /* passing NULL as the 3rd param make function to crash on older platforms */
741     err = MsiViewGetError( 0, NULL, &sz );
742     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
743
744     /* open a view */
745     query = "SELECT * FROM `phone`";
746     r = MsiDatabaseOpenView(hdb, query, &hview);
747     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
748
749     /* see what happens with a good hview and bad args */
750     err = MsiViewGetError( hview, NULL, NULL );
751     ok(err == MSIDBERROR_INVALIDARG || err == MSIDBERROR_NOERROR,
752        "MsiViewGetError returns %u (expected -3)\n", err);
753     err = MsiViewGetError( hview, buffer, NULL );
754     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
755
756     /* see what happens with a zero length buffer */
757     sz = 0;
758     buffer[0] = 'x';
759     err = MsiViewGetError( hview, buffer, &sz );
760     ok(err == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
761     ok(buffer[0] == 'x', "buffer cleared\n");
762     ok(sz == 0, "size not zero\n");
763
764     /* ok this one is strange */
765     sz = 0;
766     err = MsiViewGetError( hview, NULL, &sz );
767     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
768     ok(sz == 0, "size not zero\n");
769
770     /* see if it really has an error */
771     sz = sizeof buffer;
772     buffer[0] = 'x';
773     err = MsiViewGetError( hview, buffer, &sz );
774     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
775     ok(buffer[0] == 0, "buffer not cleared\n");
776     ok(sz == 0, "size not zero\n");
777
778     r = MsiViewExecute(hview, 0);
779     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
780
781     /* try some invalid records */
782     r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
783     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
784     r = MsiViewModify(hview, -1, 0 );
785     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
786
787     /* try an small record */
788     hrec = MsiCreateRecord(1);
789     r = MsiViewModify(hview, -1, hrec );
790     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
791
792     r = MsiCloseHandle(hrec);
793     ok(r == ERROR_SUCCESS, "failed to close record\n");
794
795     /* insert a valid record */
796     hrec = MsiCreateRecord(3);
797
798     r = MsiRecordSetInteger(hrec, 1, 1);
799     ok(r == ERROR_SUCCESS, "failed to set integer\n");
800     r = MsiRecordSetString(hrec, 2, "bob");
801     ok(r == ERROR_SUCCESS, "failed to set string\n");
802     r = MsiRecordSetString(hrec, 3, "7654321");
803     ok(r == ERROR_SUCCESS, "failed to set string\n");
804
805     r = MsiViewExecute(hview, 0);
806     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
807     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
808     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
809
810     /* insert the same thing again */
811     r = MsiViewExecute(hview, 0);
812     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
813
814     /* should fail ... */
815     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
816     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
817
818     r = MsiCloseHandle(hrec);
819     ok(r == ERROR_SUCCESS, "failed to close record\n");
820
821     r = MsiViewClose(hview);
822     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
823     r = MsiCloseHandle(hview);
824     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
825
826     query = "SELECT * FROM `phone`";
827     r = MsiDatabaseOpenView(hdb, query, &hview);
828     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
829
830     r = MsiViewExecute(hview, 0);
831     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
832
833     r = MsiViewFetch(hview, &hrec);
834     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
835
836     r = MsiRecordGetInteger(hrec, 1);
837     ok(r == 1, "Expected 1, got %d\n", r);
838
839     sz = sizeof(buffer);
840     r = MsiRecordGetString(hrec, 2, buffer, &sz);
841     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
842     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
843
844     sz = sizeof(buffer);
845     r = MsiRecordGetString(hrec, 3, buffer, &sz);
846     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
847     ok(!lstrcmp(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
848
849     /* update the view, non-primary key */
850     r = MsiRecordSetString(hrec, 3, "3141592");
851     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
852
853     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
854     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
855
856     /* do it again */
857     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
858     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
859
860     /* update the view, primary key */
861     r = MsiRecordSetInteger(hrec, 1, 5);
862     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
863
864     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
865     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
866
867     r = MsiCloseHandle(hrec);
868     ok(r == ERROR_SUCCESS, "failed to close record\n");
869
870     r = MsiViewClose(hview);
871     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
872     r = MsiCloseHandle(hview);
873     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
874
875     query = "SELECT * FROM `phone`";
876     r = MsiDatabaseOpenView(hdb, query, &hview);
877     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
878
879     r = MsiViewExecute(hview, 0);
880     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
881
882     r = MsiViewFetch(hview, &hrec);
883     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
884
885     r = MsiRecordGetInteger(hrec, 1);
886     ok(r == 1, "Expected 1, got %d\n", r);
887
888     sz = sizeof(buffer);
889     r = MsiRecordGetString(hrec, 2, buffer, &sz);
890     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
891     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
892
893     sz = sizeof(buffer);
894     r = MsiRecordGetString(hrec, 3, buffer, &sz);
895     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
896     ok(!lstrcmp(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
897
898     r = MsiCloseHandle(hrec);
899     ok(r == ERROR_SUCCESS, "failed to close record\n");
900
901     /* use a record that doesn't come from a view fetch */
902     hrec = MsiCreateRecord(3);
903     ok(hrec != 0, "MsiCreateRecord failed\n");
904
905     r = MsiRecordSetInteger(hrec, 1, 3);
906     ok(r == ERROR_SUCCESS, "failed to set integer\n");
907     r = MsiRecordSetString(hrec, 2, "jane");
908     ok(r == ERROR_SUCCESS, "failed to set string\n");
909     r = MsiRecordSetString(hrec, 3, "112358");
910     ok(r == ERROR_SUCCESS, "failed to set string\n");
911
912     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
913     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
914
915     r = MsiCloseHandle(hrec);
916     ok(r == ERROR_SUCCESS, "failed to close record\n");
917
918     /* use a record that doesn't come from a view fetch, primary key matches */
919     hrec = MsiCreateRecord(3);
920     ok(hrec != 0, "MsiCreateRecord failed\n");
921
922     r = MsiRecordSetInteger(hrec, 1, 1);
923     ok(r == ERROR_SUCCESS, "failed to set integer\n");
924     r = MsiRecordSetString(hrec, 2, "jane");
925     ok(r == ERROR_SUCCESS, "failed to set string\n");
926     r = MsiRecordSetString(hrec, 3, "112358");
927     ok(r == ERROR_SUCCESS, "failed to set string\n");
928
929     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
930     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
931
932     r = MsiCloseHandle(hrec);
933     ok(r == ERROR_SUCCESS, "failed to close record\n");
934
935     hrec = MsiCreateRecord(3);
936
937     r = MsiRecordSetInteger(hrec, 1, 2);
938     ok(r == ERROR_SUCCESS, "failed to set integer\n");
939     r = MsiRecordSetString(hrec, 2, "nick");
940     ok(r == ERROR_SUCCESS, "failed to set string\n");
941     r = MsiRecordSetString(hrec, 3, "141421");
942     ok(r == ERROR_SUCCESS, "failed to set string\n");
943
944     r = MsiViewExecute(hview, 0);
945     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
946     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
947     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
948
949     r = MsiCloseHandle(hrec);
950     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
951     r = MsiViewClose(hview);
952     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
953     r = MsiCloseHandle(hview);
954     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
955
956     query = "SELECT * FROM `phone` WHERE `id` = 1";
957     r = MsiDatabaseOpenView(hdb, query, &hview);
958     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
959     r = MsiViewExecute(hview, 0);
960     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
961     r = MsiViewFetch(hview, &hrec);
962     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
963
964     /* change the id to match the second row */
965     r = MsiRecordSetInteger(hrec, 1, 2);
966     ok(r == ERROR_SUCCESS, "failed to set integer\n");
967     r = MsiRecordSetString(hrec, 2, "jerry");
968     ok(r == ERROR_SUCCESS, "failed to set string\n");
969
970     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
971     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
972
973     r = MsiCloseHandle(hrec);
974     ok(r == ERROR_SUCCESS, "failed to close record\n");
975     r = MsiViewClose(hview);
976     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
977     r = MsiCloseHandle(hview);
978     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
979
980     /* broader search */
981     query = "SELECT * FROM `phone` ORDER BY `id`";
982     r = MsiDatabaseOpenView(hdb, query, &hview);
983     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
984     r = MsiViewExecute(hview, 0);
985     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
986     r = MsiViewFetch(hview, &hrec);
987     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
988
989     /* change the id to match the second row */
990     r = MsiRecordSetInteger(hrec, 1, 2);
991     ok(r == ERROR_SUCCESS, "failed to set integer\n");
992     r = MsiRecordSetString(hrec, 2, "jerry");
993     ok(r == ERROR_SUCCESS, "failed to set string\n");
994
995     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
996     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
997
998     r = MsiCloseHandle(hrec);
999     ok(r == ERROR_SUCCESS, "failed to close record\n");
1000     r = MsiViewClose(hview);
1001     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1002     r = MsiCloseHandle(hview);
1003     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1004
1005     r = MsiCloseHandle( hdb );
1006     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1007 }
1008
1009 static MSIHANDLE create_db(void)
1010 {
1011     MSIHANDLE hdb = 0;
1012     UINT res;
1013
1014     DeleteFile(msifile);
1015
1016     /* create an empty database */
1017     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1018     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1019     if( res != ERROR_SUCCESS )
1020         return hdb;
1021
1022     res = MsiDatabaseCommit( hdb );
1023     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1024
1025     return hdb;
1026 }
1027
1028 static void test_getcolinfo(void)
1029 {
1030     MSIHANDLE hdb, hview = 0, rec = 0;
1031     UINT r;
1032     DWORD sz;
1033     char buffer[0x20];
1034
1035     /* create an empty db */
1036     hdb = create_db();
1037     ok( hdb, "failed to create db\n");
1038
1039     /* tables should be present */
1040     r = MsiDatabaseOpenView(hdb, "select * from _Tables", &hview);
1041     ok( r == ERROR_SUCCESS, "failed to open query\n");
1042
1043     r = MsiViewExecute(hview, 0);
1044     ok( r == ERROR_SUCCESS, "failed to execute query\n");
1045
1046     /* check that NAMES works */
1047     rec = 0;
1048     r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1049     ok( r == ERROR_SUCCESS, "failed to get names\n");
1050     sz = sizeof buffer;
1051     r = MsiRecordGetString(rec, 1, buffer, &sz );
1052     ok( r == ERROR_SUCCESS, "failed to get string\n");
1053     ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
1054     r = MsiCloseHandle( rec );
1055     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1056
1057     /* check that TYPES works */
1058     rec = 0;
1059     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1060     ok( r == ERROR_SUCCESS, "failed to get names\n");
1061     sz = sizeof buffer;
1062     r = MsiRecordGetString(rec, 1, buffer, &sz );
1063     ok( r == ERROR_SUCCESS, "failed to get string\n");
1064     ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
1065     r = MsiCloseHandle( rec );
1066     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1067
1068     /* check that invalid values fail */
1069     rec = 0;
1070     r = MsiViewGetColumnInfo( hview, 100, &rec );
1071     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1072     ok( rec == 0, "returned a record\n");
1073
1074     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1075     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1076
1077     r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1078     ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1079
1080     r = MsiViewClose(hview);
1081     ok( r == ERROR_SUCCESS, "failed to close view\n");
1082     r = MsiCloseHandle(hview);
1083     ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1084     r = MsiCloseHandle(hdb);
1085     ok( r == ERROR_SUCCESS, "failed to close database\n");
1086 }
1087
1088 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1089 {
1090     MSIHANDLE hview = 0, rec = 0;
1091     UINT r;
1092
1093     r = MsiDatabaseOpenView(hdb, query, &hview);
1094     if( r != ERROR_SUCCESS )
1095         return r;
1096
1097     r = MsiViewExecute(hview, 0);
1098     if( r == ERROR_SUCCESS )
1099     {
1100         MsiViewGetColumnInfo( hview, type, &rec );
1101     }
1102     MsiViewClose(hview);
1103     MsiCloseHandle(hview);
1104     return rec;
1105 }
1106
1107 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1108 {
1109     MSIHANDLE hview = 0, rec = 0;
1110     UINT r, type = 0;
1111     char query[0x100];
1112
1113     sprintf(query, "select * from `_Columns` where  `Table` = '%s'", table );
1114
1115     r = MsiDatabaseOpenView(hdb, query, &hview);
1116     if( r != ERROR_SUCCESS )
1117         return r;
1118
1119     r = MsiViewExecute(hview, 0);
1120     if( r == ERROR_SUCCESS )
1121     {
1122         while (1)
1123         {
1124             r = MsiViewFetch( hview, &rec );
1125             if( r != ERROR_SUCCESS)
1126                 break;
1127             r = MsiRecordGetInteger( rec, 2 );
1128             if (r == field)
1129                 type = MsiRecordGetInteger( rec, 4 );
1130             MsiCloseHandle( rec );
1131         }
1132     }
1133     MsiViewClose(hview);
1134     MsiCloseHandle(hview);
1135     return type;
1136 }
1137
1138 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
1139 {
1140     CHAR buffer[0x20];
1141     UINT r;
1142     DWORD sz;
1143
1144     sz = sizeof buffer;
1145     r = MsiRecordGetString( rec, field, buffer, &sz );
1146     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1147 }
1148
1149 static void test_viewgetcolumninfo(void)
1150 {
1151     MSIHANDLE hdb = 0, rec;
1152     UINT r;
1153
1154     hdb = create_db();
1155     ok( hdb, "failed to create db\n");
1156
1157     r = run_query( hdb, 0,
1158             "CREATE TABLE `Properties` "
1159             "( `Property` CHAR(255), "
1160             "  `Value` CHAR(1), "
1161             "  `Intvalue` INT, "
1162             "  `Integervalue` INTEGER, "
1163             "  `Shortvalue` SHORT, "
1164             "  `Longvalue` LONG, "
1165             "  `Longcharvalue` LONGCHAR "
1166             "  PRIMARY KEY `Property`)" );
1167     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1168
1169     /* check the column types */
1170     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1171     ok( rec, "failed to get column info record\n" );
1172
1173     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1174     ok( check_record( rec, 2, "S1"), "wrong record type\n");
1175     ok( check_record( rec, 3, "I2"), "wrong record type\n");
1176     ok( check_record( rec, 4, "I2"), "wrong record type\n");
1177     ok( check_record( rec, 5, "I2"), "wrong record type\n");
1178     ok( check_record( rec, 6, "I4"), "wrong record type\n");
1179     ok( check_record( rec, 7, "S0"), "wrong record type\n");
1180
1181     MsiCloseHandle( rec );
1182
1183     /* check the type in _Columns */
1184     ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1185     ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1186     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1187     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1188     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1189     ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1190     ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1191
1192     /* now try the names */
1193     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1194     ok( rec, "failed to get column info record\n" );
1195
1196     ok( check_record( rec, 1, "Property"), "wrong record type\n");
1197     ok( check_record( rec, 2, "Value"), "wrong record type\n");
1198     ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
1199     ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
1200     ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
1201     ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
1202     ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
1203
1204     MsiCloseHandle( rec );
1205
1206     r = run_query( hdb, 0,
1207             "CREATE TABLE `Binary` "
1208             "( `Name` CHAR(255), `Data` OBJECT  PRIMARY KEY `Name`)" );
1209     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1210
1211     /* check the column types */
1212     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1213     ok( rec, "failed to get column info record\n" );
1214
1215     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1216     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1217
1218     MsiCloseHandle( rec );
1219
1220     /* check the type in _Columns */
1221     ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1222     ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1223
1224     /* now try the names */
1225     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1226     ok( rec, "failed to get column info record\n" );
1227
1228     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1229     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1230     MsiCloseHandle( rec );
1231
1232     r = run_query( hdb, 0,
1233             "CREATE TABLE `UIText` "
1234             "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1235     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1236
1237     ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1238     ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1239
1240     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1241     ok( rec, "failed to get column info record\n" );
1242     ok( check_record( rec, 1, "Key"), "wrong record type\n");
1243     ok( check_record( rec, 2, "Text"), "wrong record type\n");
1244     MsiCloseHandle( rec );
1245
1246     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1247     ok( rec, "failed to get column info record\n" );
1248     ok( check_record( rec, 1, "s72"), "wrong record type\n");
1249     ok( check_record( rec, 2, "L255"), "wrong record type\n");
1250     MsiCloseHandle( rec );
1251
1252     MsiCloseHandle( hdb );
1253 }
1254
1255 static void test_msiexport(void)
1256 {
1257     MSIHANDLE hdb = 0, hview = 0;
1258     UINT r;
1259     const char *query;
1260     char path[MAX_PATH];
1261     const char file[] = "phone.txt";
1262     HANDLE handle;
1263     char buffer[0x100];
1264     DWORD length;
1265     const char expected[] =
1266         "id\tname\tnumber\r\n"
1267         "I2\tS32\tS32\r\n"
1268         "phone\tid\r\n"
1269         "1\tAbe\t8675309\r\n";
1270
1271     DeleteFile(msifile);
1272
1273     /* just MsiOpenDatabase should not create a file */
1274     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1275     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1276
1277     /* create a table */
1278     query = "CREATE TABLE `phone` ( "
1279             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1280             "PRIMARY KEY `id`)";
1281     r = MsiDatabaseOpenView(hdb, query, &hview);
1282     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1283     r = MsiViewExecute(hview, 0);
1284     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1285     r = MsiViewClose(hview);
1286     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1287     r = MsiCloseHandle(hview);
1288     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1289
1290     /* insert a value into it */
1291     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1292         "VALUES('1', 'Abe', '8675309')";
1293     r = MsiDatabaseOpenView(hdb, query, &hview);
1294     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1295     r = MsiViewExecute(hview, 0);
1296     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1297     r = MsiViewClose(hview);
1298     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1299     r = MsiCloseHandle(hview);
1300     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1301
1302     GetCurrentDirectory(MAX_PATH, path);
1303
1304     r = MsiDatabaseExport(hdb, "phone", path, file);
1305     ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1306
1307     MsiCloseHandle(hdb);
1308
1309     lstrcat(path, "\\");
1310     lstrcat(path, file);
1311
1312     /* check the data that was written */
1313     length = 0;
1314     memset(buffer, 0, sizeof buffer);
1315     handle = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1316     if (handle != INVALID_HANDLE_VALUE)
1317     {
1318         ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1319         CloseHandle(handle);
1320         DeleteFile(path);
1321     }
1322     else
1323         ok(0, "failed to open file %s\n", path);
1324
1325     ok( length == strlen(expected), "length of data wrong\n");
1326     ok( !lstrcmp(buffer, expected), "data doesn't match\n");
1327     DeleteFile(msifile);
1328 }
1329
1330 static void test_longstrings(void)
1331 {
1332     const char insert_query[] = 
1333         "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1334     char *str;
1335     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1336     DWORD len;
1337     UINT r;
1338     const DWORD STRING_LENGTH = 0x10005;
1339
1340     DeleteFile(msifile);
1341     /* just MsiOpenDatabase should not create a file */
1342     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1343     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1344
1345     /* create a table */
1346     r = try_query( hdb, 
1347         "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1348     ok(r == ERROR_SUCCESS, "query failed\n");
1349
1350     /* try a insert a very long string */
1351     str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
1352     len = strchr(insert_query, 'Z') - insert_query;
1353     strcpy(str, insert_query);
1354     memset(str+len, 'Z', STRING_LENGTH);
1355     strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1356     r = try_query( hdb, str );
1357     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1358
1359     HeapFree(GetProcessHeap(), 0, str);
1360
1361     MsiDatabaseCommit(hdb);
1362     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1363     MsiCloseHandle(hdb);
1364
1365     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
1366     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1367
1368     r = MsiDatabaseOpenView(hdb, "select * from `strings` where `id` = 1", &hview);
1369     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1370
1371     r = MsiViewExecute(hview, 0);
1372     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1373
1374     r = MsiViewFetch(hview, &hrec);
1375     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1376
1377     MsiViewClose(hview);
1378     MsiCloseHandle(hview);
1379
1380     r = MsiRecordGetString(hrec, 2, NULL, &len);
1381     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1382     ok(len == STRING_LENGTH, "string length wrong\n");
1383
1384     MsiCloseHandle(hrec);
1385     MsiCloseHandle(hdb);
1386     DeleteFile(msifile);
1387 }
1388
1389 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1390 {
1391     HANDLE file;
1392     DWORD written;
1393
1394     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1395     if (file == INVALID_HANDLE_VALUE)
1396         return;
1397
1398     WriteFile(file, data, strlen(data), &written, NULL);
1399     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1400
1401     if (size)
1402     {
1403         SetFilePointer(file, size, NULL, FILE_BEGIN);
1404         SetEndOfFile(file);
1405     }
1406
1407     CloseHandle(file);
1408 }
1409
1410 #define create_file(name) create_file_data(name, name, 0)
1411  
1412 static void test_streamtable(void)
1413 {
1414     MSIHANDLE hdb = 0, rec, view, hsi;
1415     char file[MAX_PATH];
1416     char buf[MAX_PATH];
1417     DWORD size;
1418     UINT r;
1419
1420     hdb = create_db();
1421     ok( hdb, "failed to create db\n");
1422
1423     r = run_query( hdb, 0,
1424             "CREATE TABLE `Properties` "
1425             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
1426     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1427
1428     r = run_query( hdb, 0,
1429             "INSERT INTO `Properties` "
1430             "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1431     ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1432
1433     r = MsiDatabaseCommit( hdb );
1434     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1435
1436     MsiCloseHandle( hdb );
1437
1438     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
1439     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1440
1441     /* check the column types */
1442     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1443     ok( rec, "failed to get column info record\n" );
1444
1445     ok( check_record( rec, 1, "s62"), "wrong record type\n");
1446     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1447
1448     MsiCloseHandle( rec );
1449
1450     /* now try the names */
1451     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1452     ok( rec, "failed to get column info record\n" );
1453
1454     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1455     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1456
1457     MsiCloseHandle( rec );
1458
1459     r = MsiDatabaseOpenView( hdb,
1460             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1461     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1462
1463     r = MsiViewExecute( view, 0 );
1464     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1465
1466     r = MsiViewFetch( view, &rec );
1467     ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1468
1469     MsiCloseHandle( rec );
1470     MsiViewClose( view );
1471     MsiCloseHandle( view );
1472
1473     /* create a summary information stream */
1474     r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1475     ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1476
1477     r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1478     ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1479
1480     r = MsiSummaryInfoPersist( hsi );
1481     ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1482
1483     MsiCloseHandle( hsi );
1484
1485     r = MsiDatabaseOpenView( hdb,
1486             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1487     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1488
1489     r = MsiViewExecute( view, 0 );
1490     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1491
1492     r = MsiViewFetch( view, &rec );
1493     ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1494
1495     MsiCloseHandle( rec );
1496     MsiViewClose( view );
1497     MsiCloseHandle( view );
1498
1499     /* insert a file into the _Streams table */
1500     create_file( "test.txt" );
1501
1502     rec = MsiCreateRecord( 2 );
1503     MsiRecordSetString( rec, 1, "data" );
1504
1505     r = MsiRecordSetStream( rec, 2, "test.txt" );
1506     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1507
1508     DeleteFile("test.txt");
1509
1510     r = MsiDatabaseOpenView( hdb,
1511             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1512     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1513
1514     r = MsiViewExecute( view, rec );
1515     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1516
1517     MsiCloseHandle( rec );
1518     MsiViewClose( view );
1519     MsiCloseHandle( view );
1520
1521     /* insert another one */
1522     create_file( "test1.txt" );
1523
1524     rec = MsiCreateRecord( 2 );
1525     MsiRecordSetString( rec, 1, "data1" );
1526
1527     r = MsiRecordSetStream( rec, 2, "test1.txt" );
1528     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1529
1530     DeleteFile("test1.txt");
1531
1532     r = MsiDatabaseOpenView( hdb,
1533             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1534     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1535
1536     r = MsiViewExecute( view, rec );
1537     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1538
1539     MsiCloseHandle( rec );
1540     MsiViewClose( view );
1541     MsiCloseHandle( view );
1542
1543     r = MsiDatabaseOpenView( hdb,
1544             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1545     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1546
1547     r = MsiViewExecute( view, 0 );
1548     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1549
1550     r = MsiViewFetch( view, &rec );
1551     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1552
1553     size = MAX_PATH;
1554     r = MsiRecordGetString( rec, 1, file, &size );
1555     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1556     ok( !lstrcmp(file, "data"), "Expected 'data', got %s\n", file);
1557
1558     size = MAX_PATH;
1559     memset(buf, 0, MAX_PATH);
1560     r = MsiRecordReadStream( rec, 2, buf, &size );
1561     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1562     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf);
1563
1564     MsiCloseHandle( rec );
1565     MsiViewClose( view );
1566     MsiCloseHandle( view );
1567
1568     r = MsiDatabaseOpenView( hdb,
1569             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1570     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1571
1572     r = MsiViewExecute( view, 0 );
1573     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1574
1575     r = MsiViewFetch( view, &rec );
1576     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1577
1578     size = MAX_PATH;
1579     r = MsiRecordGetString( rec, 1, file, &size );
1580     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1581     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1582
1583     size = MAX_PATH;
1584     memset(buf, 0, MAX_PATH);
1585     r = MsiRecordReadStream( rec, 2, buf, &size );
1586     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1587     ok( !lstrcmp(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
1588
1589     MsiCloseHandle( rec );
1590     MsiViewClose( view );
1591     MsiCloseHandle( view );
1592
1593     /* perform an update */
1594     create_file( "test2.txt" );
1595     rec = MsiCreateRecord( 1 );
1596
1597     r = MsiRecordSetStream( rec, 1, "test2.txt" );
1598     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1599
1600     DeleteFile("test2.txt");
1601
1602     r = MsiDatabaseOpenView( hdb,
1603             "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1604     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1605
1606     r = MsiViewExecute( view, rec );
1607     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1608
1609     MsiCloseHandle( rec );
1610     MsiViewClose( view );
1611     MsiCloseHandle( view );
1612
1613     r = MsiDatabaseOpenView( hdb,
1614             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1615     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1616
1617     r = MsiViewExecute( view, 0 );
1618     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1619
1620     r = MsiViewFetch( view, &rec );
1621     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1622
1623     size = MAX_PATH;
1624     r = MsiRecordGetString( rec, 1, file, &size );
1625     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1626     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1627
1628     size = MAX_PATH;
1629     memset(buf, 0, MAX_PATH);
1630     r = MsiRecordReadStream( rec, 2, buf, &size );
1631     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1632     todo_wine ok( !lstrcmp(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
1633
1634     MsiCloseHandle( rec );
1635     MsiViewClose( view );
1636     MsiCloseHandle( view );
1637     MsiCloseHandle( hdb );
1638     DeleteFile(msifile);
1639 }
1640
1641 static void test_binary(void)
1642 {
1643     MSIHANDLE hdb = 0, rec;
1644     char file[MAX_PATH];
1645     char buf[MAX_PATH];
1646     DWORD size;
1647     LPCSTR query;
1648     UINT r;
1649
1650     /* insert a file into the Binary table */
1651     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1652     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1653
1654     query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
1655     r = run_query( hdb, 0, query );
1656     ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1657
1658     create_file( "test.txt" );
1659     rec = MsiCreateRecord( 1 );
1660     r = MsiRecordSetStream( rec, 1, "test.txt" );
1661     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1662     DeleteFile( "test.txt" );
1663
1664     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1665     r = run_query( hdb, rec, query );
1666     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1667
1668     r = MsiCloseHandle( rec );
1669     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1670
1671     r = MsiDatabaseCommit( hdb );
1672     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1673
1674     r = MsiCloseHandle( hdb );
1675     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1676
1677     /* read file from the Stream table */
1678     r = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
1679     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1680
1681     query = "SELECT * FROM `_Streams`";
1682     r = do_query( hdb, query, &rec );
1683     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1684
1685     size = MAX_PATH;
1686     r = MsiRecordGetString( rec, 1, file, &size );
1687     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1688     ok( !lstrcmp(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1689
1690     size = MAX_PATH;
1691     memset( buf, 0, MAX_PATH );
1692     r = MsiRecordReadStream( rec, 2, buf, &size );
1693     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1694     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1695
1696     r = MsiCloseHandle( rec );
1697     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1698
1699     /* read file from the Binary table */
1700     query = "SELECT * FROM `Binary`";
1701     r = do_query( hdb, query, &rec );
1702     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1703
1704     size = MAX_PATH;
1705     r = MsiRecordGetString( rec, 1, file, &size );
1706     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1707     ok( !lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file );
1708
1709     size = MAX_PATH;
1710     memset( buf, 0, MAX_PATH );
1711     r = MsiRecordReadStream( rec, 3, buf, &size );
1712     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1713     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1714
1715     r = MsiCloseHandle( rec );
1716     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1717
1718     r = MsiCloseHandle( hdb );
1719     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1720
1721     DeleteFile( msifile );
1722 }
1723
1724 static void test_where_not_in_selected(void)
1725 {
1726     MSIHANDLE hdb = 0, rec, view;
1727     LPCSTR query;
1728     UINT r;
1729
1730     hdb = create_db();
1731     ok( hdb, "failed to create db\n");
1732
1733     r = run_query(hdb, 0,
1734             "CREATE TABLE `IESTable` ("
1735             "`Action` CHAR(64), "
1736             "`Condition` CHAR(64), "
1737             "`Sequence` LONG PRIMARY KEY `Sequence`)");
1738     ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1739
1740     r = run_query(hdb, 0,
1741             "CREATE TABLE `CATable` ("
1742             "`Action` CHAR(64), "
1743             "`Type` LONG PRIMARY KEY `Type`)");
1744     ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1745
1746     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1747             "( `Action`, `Condition`, `Sequence`) "
1748             "VALUES ( 'clean', 'cond4', 4)");
1749     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1750
1751     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1752             "( `Action`, `Condition`, `Sequence`) "
1753             "VALUES ( 'depends', 'cond1', 1)");
1754     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1755
1756     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1757             "( `Action`, `Condition`, `Sequence`) "
1758             "VALUES ( 'build', 'cond2', 2)");
1759     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1760
1761     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1762             "( `Action`, `Condition`, `Sequence`) "
1763             "VALUES ( 'build2', 'cond6', 6)");
1764     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1765
1766     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1767             "( `Action`, `Condition`, `Sequence`) "
1768             "VALUES ( 'build', 'cond3', 3)");
1769     ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1770
1771     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1772             "( `Action`, `Type` ) "
1773             "VALUES ( 'build', 32)");
1774     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1775
1776     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1777             "( `Action`, `Type` ) "
1778             "VALUES ( 'depends', 64)");
1779     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1780
1781     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1782             "( `Action`, `Type` ) "
1783             "VALUES ( 'clean', 63)");
1784     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1785
1786     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1787             "( `Action`, `Type` ) "
1788             "VALUES ( 'build2', 34)");
1789     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1790     query = "Select IESTable.Condition from CATable, IESTable where "
1791             "CATable.Action = IESTable.Action and CATable.Type = 32";
1792     r = MsiDatabaseOpenView(hdb, query, &view);
1793     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1794
1795     r = MsiViewExecute(view, 0);
1796     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1797
1798     r = MsiViewFetch(view, &rec);
1799     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1800
1801     ok( check_record( rec, 1, "cond2"), "wrong condition\n");
1802
1803     MsiCloseHandle( rec );
1804     r = MsiViewFetch(view, &rec);
1805     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1806
1807     ok( check_record( rec, 1, "cond3"), "wrong condition\n");
1808
1809     MsiCloseHandle( rec );
1810     MsiViewClose(view);
1811     MsiCloseHandle(view);
1812
1813     MsiCloseHandle( hdb );
1814     DeleteFile(msifile);
1815
1816 }
1817
1818
1819 static void test_where(void)
1820 {
1821     MSIHANDLE hdb = 0, rec, view;
1822     LPCSTR query;
1823     UINT r;
1824     DWORD size;
1825     CHAR buf[MAX_PATH];
1826     UINT count;
1827
1828     hdb = create_db();
1829     ok( hdb, "failed to create db\n");
1830
1831     r = run_query( hdb, 0,
1832             "CREATE TABLE `Media` ("
1833             "`DiskId` SHORT NOT NULL, "
1834             "`LastSequence` LONG, "
1835             "`DiskPrompt` CHAR(64) LOCALIZABLE, "
1836             "`Cabinet` CHAR(255), "
1837             "`VolumeLabel` CHAR(32), "
1838             "`Source` CHAR(72) "
1839             "PRIMARY KEY `DiskId`)" );
1840     ok( r == S_OK, "cannot create Media table: %d\n", r );
1841
1842     r = run_query( hdb, 0, "INSERT INTO `Media` "
1843             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1844             "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
1845     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1846
1847     r = run_query( hdb, 0, "INSERT INTO `Media` "
1848             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1849             "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
1850     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1851
1852     r = run_query( hdb, 0, "INSERT INTO `Media` "
1853             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1854             "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
1855     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1856
1857     query = "SELECT * FROM `Media`";
1858     r = do_query(hdb, query, &rec);
1859     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1860     ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
1861     MsiCloseHandle( rec );
1862
1863     query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
1864     r = do_query(hdb, query, &rec);
1865     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1866     ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
1867
1868     r = MsiRecordGetInteger(rec, 1);
1869     ok( 2 == r, "field wrong\n");
1870     r = MsiRecordGetInteger(rec, 2);
1871     ok( 1 == r, "field wrong\n");
1872     MsiCloseHandle( rec );
1873
1874     query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
1875     r = MsiDatabaseOpenView(hdb, query, &view);
1876     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1877
1878     r = MsiViewExecute(view, 0);
1879     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1880
1881     r = MsiViewFetch(view, &rec);
1882     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1883
1884     count = MsiRecordGetFieldCount( rec );
1885     ok( count == 1, "Expected 1 record fields, got %d\n", count );
1886
1887     size = MAX_PATH;
1888     r = MsiRecordGetString( rec, 1, buf, &size );
1889     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
1890     ok( !lstrcmp( buf, "2" ),
1891         "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
1892     MsiCloseHandle( rec );
1893
1894     r = MsiViewFetch(view, &rec);
1895     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1896
1897     size = MAX_PATH;
1898     r = MsiRecordGetString( rec, 1, buf, &size );
1899     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
1900     ok( !lstrcmp( buf, "3" ),
1901         "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
1902     MsiCloseHandle( rec );
1903
1904     r = MsiViewFetch(view, &rec);
1905     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
1906
1907     MsiViewClose(view);
1908     MsiCloseHandle(view);
1909
1910     MsiCloseHandle( rec );
1911
1912     rec = 0;
1913     query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
1914     r = do_query(hdb, query, &rec);
1915     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
1916     MsiCloseHandle( rec );
1917
1918     rec = 0;
1919     query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
1920     r = do_query(hdb, query, &rec);
1921     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
1922     MsiCloseHandle( rec );
1923
1924     rec = 0;
1925     query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
1926     r = do_query(hdb, query, &rec);
1927     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
1928     MsiCloseHandle( rec );
1929
1930     rec = 0;
1931     query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
1932     r = do_query(hdb, query, &rec);
1933     todo_wine ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
1934     MsiCloseHandle( rec );
1935
1936     rec = 0;
1937     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
1938     r = do_query(hdb, query, &rec);
1939     ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
1940     MsiCloseHandle( rec );
1941
1942     rec = MsiCreateRecord(1);
1943     MsiRecordSetString(rec, 1, "");
1944
1945     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
1946     r = MsiDatabaseOpenView(hdb, query, &view);
1947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1948     r = MsiViewExecute(view, rec);
1949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1950
1951     MsiCloseHandle(rec);
1952
1953     r = MsiViewFetch(view, &rec);
1954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1955
1956     MsiCloseHandle(rec);
1957     MsiViewClose(view);
1958     MsiCloseHandle(view);
1959
1960     MsiCloseHandle( hdb );
1961     DeleteFile(msifile);
1962 }
1963
1964 static CHAR CURR_DIR[MAX_PATH];
1965
1966 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
1967                                 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
1968                                 "TestTable\tFirstPrimaryColumn\n"
1969                                 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
1970
1971 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
1972                                   "s255\ts255\n"
1973                                   "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
1974                                   "papaya\tleaf\n"
1975                                   "papaya\tflower\n";
1976
1977 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
1978                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
1979                                 "Table\tA\r\n"
1980                                 "a\tb\tc\td\te\tf\n"
1981                                 "g\th\ti\t\rj\tk\tl\r\n";
1982
1983 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
1984                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
1985                                 "Table2\tA\r\n"
1986                                 "a\tb\tc\td\te\tf\n"
1987                                 "g\th\ti\tj\tk\tl\r\n";
1988
1989 static const CHAR suminfo[] = "PropertyId\tValue\n"
1990                               "i2\tl255\n"
1991                               "_SummaryInformation\tPropertyId\n"
1992                               "1\t1252\n"
1993                               "2\tInstaller Database\n"
1994                               "3\tInstaller description\n"
1995                               "4\tWineHQ\n"
1996                               "5\tInstaller\n"
1997                               "6\tInstaller comments\n"
1998                               "7\tIntel;1033\n"
1999                               "9\t{12345678-1234-1234-1234-123456789012}\n"
2000                               "12\t2009/04/12 15:46:11\n"
2001                               "13\t2009/04/12 15:46:11\n"
2002                               "14\t200\n"
2003                               "15\t2\n"
2004                               "18\tVim\n"
2005                               "19\t2\n";
2006
2007 static void write_file(const CHAR *filename, const char *data, int data_size)
2008 {
2009     DWORD size;
2010
2011     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
2012                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2013
2014     WriteFile(hf, data, data_size, &size, NULL);
2015     CloseHandle(hf);
2016 }
2017
2018 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2019 {
2020     UINT r;
2021
2022     write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
2023     r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2024     DeleteFileA("temp_file");
2025
2026     return r;
2027 }
2028
2029 static void test_suminfo_import(void)
2030 {
2031     MSIHANDLE hdb, hsi, view = 0;
2032     LPCSTR query;
2033     UINT r, count, size, type;
2034     char str_value[50];
2035     INT int_value;
2036     FILETIME ft_value;
2037
2038     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2039
2040     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2042
2043     r = add_table_to_db(hdb, suminfo);
2044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2045
2046     /* _SummaryInformation is not imported as a regular table... */
2047
2048     query = "SELECT * FROM `_SummaryInformation`";
2049     r = MsiDatabaseOpenViewA(hdb, query, &view);
2050     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2051     MsiCloseHandle(view);
2052
2053     /* ...its data is added to the special summary information stream */
2054
2055     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2057
2058     r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2060     ok(count == 14, "Expected 14, got %u\n", count);
2061
2062     r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2064     ok(type ==  VT_I2, "Expected VT_I2, got %u\n", type);
2065     ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2066
2067     size = sizeof(str_value);
2068     r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2070     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2071     ok(size == 18, "Expected 18, got %u\n", size);
2072     ok(!strcmp(str_value, "Installer Database"),
2073        "Expected \"Installer Database\", got %s\n", str_value);
2074
2075     size = sizeof(str_value);
2076     r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2078     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2079     ok(!strcmp(str_value, "Installer description"),
2080        "Expected \"Installer description\", got %s\n", str_value);
2081
2082     size = sizeof(str_value);
2083     r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2085     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2086     ok(!strcmp(str_value, "WineHQ"),
2087        "Expected \"WineHQ\", got %s\n", str_value);
2088
2089     size = sizeof(str_value);
2090     r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2092     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2093     ok(!strcmp(str_value, "Installer"),
2094        "Expected \"Installer\", got %s\n", str_value);
2095
2096     size = sizeof(str_value);
2097     r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2099     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2100     ok(!strcmp(str_value, "Installer comments"),
2101        "Expected \"Installer comments\", got %s\n", str_value);
2102
2103     size = sizeof(str_value);
2104     r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2106     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2107     ok(!strcmp(str_value, "Intel;1033"),
2108        "Expected \"Intel;1033\", got %s\n", str_value);
2109
2110     size = sizeof(str_value);
2111     r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2113     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2114     ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2115        "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2116
2117     r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2119     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2120
2121     r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2123     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2124
2125     r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2127     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2128     ok(int_value == 200, "Expected 200, got %d\n", int_value);
2129
2130     r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2132     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2133     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2134
2135     r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2137     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2138     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2139
2140     size = sizeof(str_value);
2141     r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2143     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2144     ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2145
2146     MsiCloseHandle(hsi);
2147     MsiCloseHandle(hdb);
2148     DeleteFileA(msifile);
2149 }
2150
2151 static void test_msiimport(void)
2152 {
2153     MSIHANDLE hdb, view, rec;
2154     LPCSTR query;
2155     UINT r, count;
2156     signed int i;
2157
2158     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2159
2160     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2162
2163     r = add_table_to_db(hdb, test_data);
2164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2165
2166     r = add_table_to_db(hdb, two_primary);
2167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2168
2169     r = add_table_to_db(hdb, endlines1);
2170     if (r == ERROR_FUNCTION_FAILED)
2171     {
2172         /* win9x doesn't handle this case */
2173         skip("endlines not handled correctly.\n");
2174         MsiCloseHandle(hdb);
2175         DeleteFileA(msifile);
2176         return;
2177     }
2178
2179     r = add_table_to_db(hdb, endlines2);
2180     ok(r == ERROR_FUNCTION_FAILED,
2181        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2182
2183     query = "SELECT * FROM `TestTable`";
2184     r = MsiDatabaseOpenView(hdb, query, &view);
2185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2186
2187     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2188     count = MsiRecordGetFieldCount(rec);
2189     ok(count == 9, "Expected 9, got %d\n", count);
2190     ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2191     ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2192     ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2193     ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2194     ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2195     ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2196     ok(check_record(rec, 7, "String"), "Expected String\n");
2197     ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2198     ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2199     MsiCloseHandle(rec);
2200
2201     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2202     count = MsiRecordGetFieldCount(rec);
2203     ok(count == 9, "Expected 9, got %d\n", count);
2204     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2205     ok(check_record(rec, 2, "i2"), "Expected i2\n");
2206     ok(check_record(rec, 3, "i2"), "Expected i2\n");
2207     ok(check_record(rec, 4, "I2"), "Expected I2\n");
2208     ok(check_record(rec, 5, "i4"), "Expected i4\n");
2209     ok(check_record(rec, 6, "I4"), "Expected I4\n");
2210     ok(check_record(rec, 7, "S255"), "Expected S255\n");
2211     ok(check_record(rec, 8, "S0"), "Expected S0\n");
2212     ok(check_record(rec, 9, "s0"), "Expected s0\n");
2213     MsiCloseHandle(rec);
2214
2215     query = "SELECT * FROM `TestTable`";
2216     r = do_query(hdb, query, &rec);
2217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2218     ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2219     ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2220     ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2221     ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2222
2223     i = MsiRecordGetInteger(rec, 2);
2224     ok(i == 5, "Expected 5, got %d\n", i);
2225
2226     i = MsiRecordGetInteger(rec, 3);
2227     ok(i == 2, "Expected 2, got %d\n", i);
2228
2229     i = MsiRecordGetInteger(rec, 4);
2230     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2231
2232     i = MsiRecordGetInteger(rec, 5);
2233     ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2234
2235     i = MsiRecordGetInteger(rec, 6);
2236     ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2237
2238     MsiCloseHandle(rec);
2239     MsiViewClose(view);
2240     MsiCloseHandle(view);
2241
2242     query = "SELECT * FROM `TwoPrimary`";
2243     r = MsiDatabaseOpenView(hdb, query, &view);
2244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2245
2246     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2247     count = MsiRecordGetFieldCount(rec);
2248     ok(count == 2, "Expected 2, got %d\n", count);
2249     ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2250     ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2251
2252     MsiCloseHandle(rec);
2253
2254     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2255     count = MsiRecordGetFieldCount(rec);
2256     ok(count == 2, "Expected 2, got %d\n", count);
2257     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2258     ok(check_record(rec, 2, "s255"), "Expected s255\n");
2259     MsiCloseHandle(rec);
2260
2261     r = MsiViewExecute(view, 0);
2262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2263
2264     r = MsiViewFetch(view, &rec);
2265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2266
2267     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2268     ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2269
2270     MsiCloseHandle(rec);
2271
2272     r = MsiViewFetch(view, &rec);
2273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2274
2275     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2276     ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2277
2278     MsiCloseHandle(rec);
2279
2280     r = MsiViewFetch(view, &rec);
2281     ok(r == ERROR_NO_MORE_ITEMS,
2282        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2283
2284     r = MsiViewClose(view);
2285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2286
2287     MsiCloseHandle(view);
2288
2289     query = "SELECT * FROM `Table`";
2290     r = MsiDatabaseOpenView(hdb, query, &view);
2291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2292
2293     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2294     count = MsiRecordGetFieldCount(rec);
2295     ok(count == 6, "Expected 6, got %d\n", count);
2296     ok(check_record(rec, 1, "A"), "Expected A\n");
2297     ok(check_record(rec, 2, "B"), "Expected B\n");
2298     ok(check_record(rec, 3, "C"), "Expected C\n");
2299     ok(check_record(rec, 4, "D"), "Expected D\n");
2300     ok(check_record(rec, 5, "E"), "Expected E\n");
2301     ok(check_record(rec, 6, "F"), "Expected F\n");
2302     MsiCloseHandle(rec);
2303
2304     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2305     count = MsiRecordGetFieldCount(rec);
2306     ok(count == 6, "Expected 6, got %d\n", count);
2307     ok(check_record(rec, 1, "s72"), "Expected s72\n");
2308     ok(check_record(rec, 2, "s72"), "Expected s72\n");
2309     ok(check_record(rec, 3, "s72"), "Expected s72\n");
2310     ok(check_record(rec, 4, "s72"), "Expected s72\n");
2311     ok(check_record(rec, 5, "s72"), "Expected s72\n");
2312     ok(check_record(rec, 6, "s72"), "Expected s72\n");
2313     MsiCloseHandle(rec);
2314
2315     MsiViewClose(view);
2316     MsiCloseHandle(view);
2317
2318     query = "SELECT * FROM `Table`";
2319     r = MsiDatabaseOpenView(hdb, query, &view);
2320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2321
2322     r = MsiViewExecute(view, 0);
2323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2324
2325     r = MsiViewFetch(view, &rec);
2326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2327     ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2328     ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2329     ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2330     ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2331     ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2332     ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2333
2334     MsiCloseHandle(rec);
2335
2336     r = MsiViewFetch(view, &rec);
2337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2338     ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2339     ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2340     ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2341     ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2342     ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2343     ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2344
2345     MsiCloseHandle(rec);
2346
2347     r = MsiViewFetch(view, &rec);
2348     ok(r == ERROR_NO_MORE_ITEMS,
2349        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2350
2351     MsiViewClose(view);
2352     MsiCloseHandle(view);
2353     MsiCloseHandle(hdb);
2354     DeleteFileA(msifile);
2355 }
2356
2357 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2358                                      "s72\tV0\r\n"
2359                                      "Binary\tName\r\n"
2360                                      "filename1\tfilename1.ibd\r\n";
2361
2362 static void test_binary_import(void)
2363 {
2364     MSIHANDLE hdb = 0, rec;
2365     char file[MAX_PATH];
2366     char buf[MAX_PATH];
2367     char path[MAX_PATH];
2368     DWORD size;
2369     LPCSTR query;
2370     UINT r;
2371
2372     /* create files to import */
2373     write_file("bin_import.idt", bin_import_dat,
2374           (sizeof(bin_import_dat) - 1) * sizeof(char));
2375     CreateDirectory("bin_import", NULL);
2376     create_file_data("bin_import/filename1.ibd", "just some words", 15);
2377
2378     /* import files into database */
2379     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
2380     ok( r == ERROR_SUCCESS , "Failed to open database\n");
2381
2382     GetCurrentDirectory(MAX_PATH, path);
2383     r = MsiDatabaseImport(hdb, path, "bin_import.idt");
2384     ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2385
2386     /* read file from the Binary table */
2387     query = "SELECT * FROM `Binary`";
2388     r = do_query(hdb, query, &rec);
2389     ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2390
2391     size = MAX_PATH;
2392     r = MsiRecordGetString(rec, 1, file, &size);
2393     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2394     ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file);
2395
2396     size = MAX_PATH;
2397     memset(buf, 0, MAX_PATH);
2398     r = MsiRecordReadStream(rec, 2, buf, &size);
2399     ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2400     ok(!lstrcmp(buf, "just some words"),
2401         "Expected 'just some words', got %s\n", buf);
2402
2403     r = MsiCloseHandle(rec);
2404     ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2405
2406     r = MsiCloseHandle(hdb);
2407     ok(r == ERROR_SUCCESS , "Failed to close database\n");
2408
2409     DeleteFile("bin_import/filename1.ibd");
2410     RemoveDirectory("bin_import");
2411     DeleteFile("bin_import.idt");
2412 }
2413
2414 static void test_markers(void)
2415 {
2416     MSIHANDLE hdb, rec;
2417     LPCSTR query;
2418     UINT r;
2419
2420     hdb = create_db();
2421     ok( hdb, "failed to create db\n");
2422
2423     rec = MsiCreateRecord(3);
2424     MsiRecordSetString(rec, 1, "Table");
2425     MsiRecordSetString(rec, 2, "Apples");
2426     MsiRecordSetString(rec, 3, "Oranges");
2427
2428     /* try a legit create */
2429     query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2430     r = run_query(hdb, 0, query);
2431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2432     MsiCloseHandle(rec);
2433
2434     /* try table name as marker */
2435     rec = MsiCreateRecord(1);
2436     MsiRecordSetString(rec, 1, "Fable");
2437     query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2438     r = run_query(hdb, rec, query);
2439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2440
2441     /* verify that we just created a table called '?', not 'Fable' */
2442     r = try_query(hdb, "SELECT * from `Fable`");
2443     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2444
2445     r = try_query(hdb, "SELECT * from `?`");
2446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2447
2448     /* try table name as marker without backticks */
2449     MsiRecordSetString(rec, 1, "Mable");
2450     query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2451     r = run_query(hdb, rec, query);
2452     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2453
2454     /* try one column name as marker */
2455     MsiRecordSetString(rec, 1, "One");
2456     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2457     r = run_query(hdb, rec, query);
2458     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2459     MsiCloseHandle(rec);
2460
2461     /* try column names as markers */
2462     rec = MsiCreateRecord(2);
2463     MsiRecordSetString(rec, 1, "One");
2464     MsiRecordSetString(rec, 2, "Two");
2465     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2466     r = run_query(hdb, rec, query);
2467     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2468     MsiCloseHandle(rec);
2469
2470     /* try names with backticks */
2471     rec = MsiCreateRecord(3);
2472     MsiRecordSetString(rec, 1, "One");
2473     MsiRecordSetString(rec, 2, "Two");
2474     MsiRecordSetString(rec, 3, "One");
2475     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2476     r = run_query(hdb, rec, query);
2477     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2478
2479     /* try names with backticks, minus definitions */
2480     query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2481     r = run_query(hdb, rec, query);
2482     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2483
2484     /* try names without backticks */
2485     query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2486     r = run_query(hdb, rec, query);
2487     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2488     MsiCloseHandle(rec);
2489
2490     /* try one long marker */
2491     rec = MsiCreateRecord(1);
2492     MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2493     query = "CREATE TABLE `Mable` ( ? )";
2494     r = run_query(hdb, rec, query);
2495     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2496     MsiCloseHandle(rec);
2497
2498     /* try all names as markers */
2499     rec = MsiCreateRecord(4);
2500     MsiRecordSetString(rec, 1, "Mable");
2501     MsiRecordSetString(rec, 2, "One");
2502     MsiRecordSetString(rec, 3, "Two");
2503     MsiRecordSetString(rec, 4, "One");
2504     query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2505     r = run_query(hdb, rec, query);
2506     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2507     MsiCloseHandle(rec);
2508
2509     /* try a legit insert */
2510     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2511     r = run_query(hdb, 0, query);
2512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2513
2514     r = try_query(hdb, "SELECT * from `Table`");
2515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2516
2517     /* try values as markers */
2518     rec = MsiCreateRecord(2);
2519     MsiRecordSetInteger(rec, 1, 4);
2520     MsiRecordSetString(rec, 2, "hi");
2521     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2522     r = run_query(hdb, rec, query);
2523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2524     MsiCloseHandle(rec);
2525
2526     /* try column names and values as markers */
2527     rec = MsiCreateRecord(4);
2528     MsiRecordSetString(rec, 1, "One");
2529     MsiRecordSetString(rec, 2, "Two");
2530     MsiRecordSetInteger(rec, 3, 5);
2531     MsiRecordSetString(rec, 4, "hi");
2532     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2533     r = run_query(hdb, rec, query);
2534     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2535     MsiCloseHandle(rec);
2536
2537     /* try column names as markers */
2538     rec = MsiCreateRecord(2);
2539     MsiRecordSetString(rec, 1, "One");
2540     MsiRecordSetString(rec, 2, "Two");
2541     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2542     r = run_query(hdb, rec, query);
2543     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2544     MsiCloseHandle(rec);
2545
2546     /* try table name as a marker */
2547     rec = MsiCreateRecord(1);
2548     MsiRecordSetString(rec, 1, "Table");
2549     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2550     r = run_query(hdb, rec, query);
2551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2552     MsiCloseHandle(rec);
2553
2554     /* try table name and values as markers */
2555     rec = MsiCreateRecord(3);
2556     MsiRecordSetString(rec, 1, "Table");
2557     MsiRecordSetInteger(rec, 2, 10);
2558     MsiRecordSetString(rec, 3, "haha");
2559     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2560     r = run_query(hdb, rec, query);
2561     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2562     MsiCloseHandle(rec);
2563
2564     /* try all markers */
2565     rec = MsiCreateRecord(5);
2566     MsiRecordSetString(rec, 1, "Table");
2567     MsiRecordSetString(rec, 1, "One");
2568     MsiRecordSetString(rec, 1, "Two");
2569     MsiRecordSetInteger(rec, 2, 10);
2570     MsiRecordSetString(rec, 3, "haha");
2571     query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2572     r = run_query(hdb, rec, query);
2573     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2574     MsiCloseHandle(rec);
2575
2576     /* insert an integer as a string */
2577     rec = MsiCreateRecord(2);
2578     MsiRecordSetString(rec, 1, "11");
2579     MsiRecordSetString(rec, 2, "hi");
2580     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2581     r = run_query(hdb, rec, query);
2582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2583     MsiCloseHandle(rec);
2584
2585     /* leave off the '' for the string */
2586     rec = MsiCreateRecord(2);
2587     MsiRecordSetInteger(rec, 1, 12);
2588     MsiRecordSetString(rec, 2, "hi");
2589     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2590     r = run_query(hdb, rec, query);
2591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2592     MsiCloseHandle(rec);
2593
2594     MsiCloseHandle(hdb);
2595     DeleteFileA(msifile);
2596 }
2597
2598 #define MY_NVIEWS 4000    /* Largest installer I've seen uses < 2k */
2599 static void test_handle_limit(void)
2600 {
2601     int i;
2602     MSIHANDLE hdb;
2603     MSIHANDLE hviews[MY_NVIEWS];
2604     UINT r;
2605
2606     /* create an empty db */
2607     hdb = create_db();
2608     ok( hdb, "failed to create db\n");
2609
2610     memset(hviews, 0, sizeof(hviews));
2611
2612     for (i=0; i<MY_NVIEWS; i++) {
2613         static char szQueryBuf[256] = "SELECT * from `_Tables`";
2614         hviews[i] = 0xdeadbeeb;
2615         r = MsiDatabaseOpenView(hdb, szQueryBuf, &hviews[i]);
2616         if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 
2617             hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2618             break;
2619     }
2620
2621     ok( i == MY_NVIEWS, "problem opening views\n");
2622
2623     for (i=0; i<MY_NVIEWS; i++) {
2624         if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2625             MsiViewClose(hviews[i]);
2626             r = MsiCloseHandle(hviews[i]);
2627             if (r != ERROR_SUCCESS)
2628                 break;
2629         }
2630     }
2631
2632     ok( i == MY_NVIEWS, "problem closing views\n");
2633
2634     r = MsiCloseHandle(hdb);
2635     ok( r == ERROR_SUCCESS, "failed to close database\n");
2636 }
2637
2638 static void generate_transform(void)
2639 {
2640     MSIHANDLE hdb1, hdb2, hrec;
2641     LPCSTR query;
2642     UINT r;
2643
2644     /* start with two identical databases */
2645     CopyFile(msifile2, msifile, FALSE);
2646
2647     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb1 );
2648     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2649
2650     r = MsiDatabaseCommit( hdb1 );
2651     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2652
2653     r = MsiOpenDatabase(msifile2, MSIDBOPEN_READONLY, &hdb2 );
2654     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2655
2656     /* the transform between two identical database should be empty */
2657     r = MsiDatabaseGenerateTransform(hdb1, hdb2, NULL, 0, 0);
2658     todo_wine {
2659     ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2660     }
2661
2662     query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2663     r = run_query(hdb1, 0, query);
2664     ok(r == ERROR_SUCCESS, "failed to add table\n");
2665
2666     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2667     r = run_query(hdb1, 0, query);
2668     ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2669
2670     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2671     r = run_query(hdb1, 0, query);
2672     ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2673
2674     query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2675     r = run_query(hdb1, 0, query);
2676     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2677
2678     query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2679     r = run_query(hdb1, 0, query);
2680     ok(r == ERROR_SUCCESS, "failed to delete row\n");
2681
2682     hrec = MsiCreateRecord(2);
2683     r = MsiRecordSetInteger(hrec, 1, 1);
2684     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2685
2686     write_file("testdata.bin", "naengmyon", 9);
2687     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
2688     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2689
2690     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2691     r = run_query(hdb1, hrec, query);
2692     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2693
2694     MsiCloseHandle(hrec);
2695
2696     query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2697     r = run_query(hdb1, 0, query);
2698     ok(r == ERROR_SUCCESS, "failed to add column\n");
2699
2700     query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2701     r = run_query(hdb1, 0, query);
2702     ok(r == ERROR_SUCCESS, "failed to add column\n");
2703
2704     query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2705     r = run_query(hdb1, 0, query);
2706     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2707
2708     query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2709             "`Value` CHAR(0) PRIMARY KEY `Property`)";
2710     r = run_query(hdb1, 0, query);
2711     ok(r == ERROR_SUCCESS, "failed to add property table\n");
2712
2713     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2714     r = run_query(hdb1, 0, query);
2715     ok(r == ERROR_SUCCESS, "failed to add property\n");
2716
2717     /* database needs to be committed */
2718     MsiDatabaseCommit(hdb1);
2719
2720     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2721     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2722
2723     MsiCloseHandle( hdb1 );
2724     MsiCloseHandle( hdb2 );
2725
2726     DeleteFile("testdata.bin");
2727 }
2728
2729 /* data for generating a transform */
2730
2731 /* tables transform names - encoded as they would be in an msi database file */
2732 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2733 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2734 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2735 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2736 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2737 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2738 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2739 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2740 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2741
2742 /* data in each table */
2743 static const WCHAR data1[] = { /* AAR */
2744     0x0201, 0x0008, 0x8001,  /* 0x0201 = add row (1), two shorts */
2745     0x0201, 0x0009, 0x8002,
2746 };
2747 static const WCHAR data2[] = { /* _Columns */
2748     0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2749     0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2750     0x0401, 0x0005, 0x0000, 0x0006, 0xbdff,  /* 0x0401 = add row (1), 4 shorts */
2751     0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2752     0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2753     0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2754 };
2755 static const WCHAR data3[] = { /* _Tables */
2756     0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2757     0x0101, 0x000a,
2758 };
2759 static const char data4[] = /* _StringData */
2760     "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval";  /* all the strings squashed together */
2761 static const WCHAR data5[] = { /* _StringPool */
2762 /*  len, refs */
2763     0,   0,    /* string 0 ''    */
2764     3,   2,    /* string 1 'MOO' */
2765     3,   1,    /* string 2 'COW' */
2766     3,   1,    /* string 3 'PIG' */
2767     1,   1,    /* string 4 'c'   */
2768     3,   3,    /* string 5 'AAR' */
2769     3,   1,    /* string 6 'CAR' */
2770     3,   1,    /* string 7 'BAR' */
2771     2,   1,    /* string 8 'vw'  */
2772     3,   1,    /* string 9 'bmw' */
2773     8,   4,    /* string 10 'Property' */
2774     5,   1,    /* string 11 'Value' */
2775     4,   1,    /* string 12 'prop' */
2776     3,   1,    /* string 13 'val' */
2777 };
2778 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2779 static const WCHAR data6[] = { /* MOO */
2780     0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2781     0x0000, 0x8003,         /* delete row */
2782 };
2783
2784 static const WCHAR data7[] = { /* BINARY */
2785     0x0201, 0x8001, 0x0001,
2786 };
2787
2788 static const char data8[] =  /* stream data for the BINARY table */
2789     "naengmyon";
2790
2791 static const WCHAR data9[] = { /* Property */
2792     0x0201, 0x000c, 0x000d,
2793 };
2794
2795 static const struct {
2796     LPCWSTR name;
2797     const void *data;
2798     DWORD size;
2799 } table_transform_data[] =
2800 {
2801     { name1, data1, sizeof data1 },
2802     { name2, data2, sizeof data2 },
2803     { name3, data3, sizeof data3 },
2804     { name4, data4, sizeof data4 - 1 },
2805     { name5, data5, sizeof data5 },
2806     { name6, data6, sizeof data6 },
2807     { name7, data7, sizeof data7 },
2808     { name8, data8, sizeof data8 - 1 },
2809     { name9, data9, sizeof data9 },
2810 };
2811
2812 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2813
2814 static void generate_transform_manual(void)
2815 {
2816     IStorage *stg = NULL;
2817     IStream *stm;
2818     WCHAR name[0x20];
2819     HRESULT r;
2820     DWORD i, count;
2821     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2822
2823     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2824
2825     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2826
2827     r = StgCreateDocfile(name, mode, 0, &stg);
2828     ok(r == S_OK, "failed to create storage\n");
2829     if (!stg)
2830         return;
2831
2832     r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2833     ok(r == S_OK, "failed to set storage type\n");
2834
2835     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2836     {
2837         r = IStorage_CreateStream( stg, table_transform_data[i].name,
2838                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2839         if (FAILED(r))
2840         {
2841             ok(0, "failed to create stream %08x\n", r);
2842             continue;
2843         }
2844
2845         r = IStream_Write( stm, table_transform_data[i].data,
2846                           table_transform_data[i].size, &count );
2847         if (FAILED(r) || count != table_transform_data[i].size)
2848             ok(0, "failed to write stream\n");
2849         IStream_Release(stm);
2850     }
2851
2852     IStorage_Release(stg);
2853 }
2854
2855 static UINT set_summary_info(MSIHANDLE hdb)
2856 {
2857     UINT res;
2858     MSIHANDLE suminfo;
2859
2860     /* build summary info */
2861     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
2862     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2863
2864     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
2865                         "Installation Database");
2866     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2867
2868     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
2869                         "Installation Database");
2870     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2871
2872     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
2873                         "Wine Hackers");
2874     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2875
2876     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
2877                     ";1033");
2878     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2879
2880     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
2881                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
2882     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2883
2884     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
2885     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2886
2887     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
2888     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2889
2890     res = MsiSummaryInfoPersist(suminfo);
2891     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
2892
2893     res = MsiCloseHandle( suminfo);
2894     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
2895
2896     return res;
2897 }
2898
2899 static MSIHANDLE create_package_db(LPCSTR filename)
2900 {
2901     MSIHANDLE hdb = 0;
2902     UINT res;
2903
2904     DeleteFile(msifile);
2905
2906     /* create an empty database */
2907     res = MsiOpenDatabase(filename, MSIDBOPEN_CREATE, &hdb );
2908     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
2909     if( res != ERROR_SUCCESS )
2910         return hdb;
2911
2912     res = MsiDatabaseCommit( hdb );
2913     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
2914
2915     res = set_summary_info(hdb);
2916
2917     res = create_directory_table(hdb);
2918     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
2919
2920     return hdb;
2921 }
2922
2923 static MSIHANDLE package_from_db(MSIHANDLE hdb)
2924 {
2925     UINT res;
2926     CHAR szPackage[10];
2927     MSIHANDLE hPackage;
2928
2929     sprintf(szPackage,"#%i",hdb);
2930     res = MsiOpenPackage(szPackage,&hPackage);
2931     if (res != ERROR_SUCCESS)
2932         return 0;
2933
2934     res = MsiCloseHandle(hdb);
2935     if (res != ERROR_SUCCESS)
2936         return 0;
2937
2938     return hPackage;
2939 }
2940
2941 static void test_try_transform(void)
2942 {
2943     MSIHANDLE hdb, hview, hrec, hpkg;
2944     LPCSTR query;
2945     UINT r;
2946     DWORD sz;
2947     char buffer[MAX_PATH];
2948
2949     DeleteFile(msifile);
2950     DeleteFile(mstfile);
2951
2952     /* create the database */
2953     hdb = create_package_db(msifile);
2954     ok(hdb, "Failed to create package db\n");
2955
2956     query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
2957     r = run_query(hdb, 0, query);
2958     ok(r == ERROR_SUCCESS, "failed to add table\n");
2959
2960     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
2961     r = run_query(hdb, 0, query);
2962     ok(r == ERROR_SUCCESS, "failed to add row\n");
2963
2964     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
2965     r = run_query(hdb, 0, query);
2966     ok(r == ERROR_SUCCESS, "failed to add row\n");
2967
2968     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
2969     r = run_query(hdb, 0, query);
2970     ok(r == ERROR_SUCCESS, "failed to add row\n");
2971
2972     query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
2973     r = run_query(hdb, 0, query);
2974     ok(r == ERROR_SUCCESS, "failed to add table\n");
2975
2976     hrec = MsiCreateRecord(2);
2977     r = MsiRecordSetInteger(hrec, 1, 2);
2978     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2979
2980     write_file("testdata.bin", "lamyon", 6);
2981     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
2982     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2983
2984     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2985     r = run_query(hdb, hrec, query);
2986     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2987
2988     MsiCloseHandle(hrec);
2989
2990     r = MsiDatabaseCommit( hdb );
2991     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2992
2993     MsiCloseHandle( hdb );
2994     DeleteFileA("testdata.bin");
2995
2996     /*
2997      * Both these generate an equivalent transform,
2998      *  but the first doesn't work in Wine yet
2999      *  because MsiDatabaseGenerateTransform is unimplemented.
3000      */
3001     if (0)
3002         generate_transform();
3003     else
3004         generate_transform_manual();
3005
3006     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb );
3007     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3008
3009     r = MsiDatabaseApplyTransform( hdb, mstfile, 0 );
3010     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3011
3012     MsiDatabaseCommit( hdb );
3013
3014     /* check new values */
3015     hrec = 0;
3016     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3017     r = do_query(hdb, query, &hrec);
3018     ok(r == ERROR_SUCCESS, "select query failed\n");
3019     MsiCloseHandle(hrec);
3020
3021     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3022     hrec = 0;
3023     r = do_query(hdb, query, &hrec);
3024     ok(r == ERROR_SUCCESS, "select query failed\n");
3025     MsiCloseHandle(hrec);
3026
3027     /* check updated values */
3028     hrec = 0;
3029     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3030     r = do_query(hdb, query, &hrec);
3031     ok(r == ERROR_SUCCESS, "select query failed\n");
3032     MsiCloseHandle(hrec);
3033
3034     /* check unchanged value */
3035     hrec = 0;
3036     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3037     r = do_query(hdb, query, &hrec);
3038     ok(r == ERROR_SUCCESS, "select query failed\n");
3039     MsiCloseHandle(hrec);
3040
3041     /* check deleted value */
3042     hrec = 0;
3043     query = "select * from `MOO` where `NOO` = 3";
3044     r = do_query(hdb, query, &hrec);
3045     ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3046     if (hrec) MsiCloseHandle(hrec);
3047
3048     /* check added stream */
3049     hrec = 0;
3050     query = "select `BLOB` from `BINARY` where `ID` = 1";
3051     r = do_query(hdb, query, &hrec);
3052     ok(r == ERROR_SUCCESS, "select query failed\n");
3053
3054     /* check the contents of the stream */
3055     sz = sizeof buffer;
3056     r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3057     ok(r == ERROR_SUCCESS, "read stream failed\n");
3058     ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3059     ok(sz == 9, "stream data was wrong size\n");
3060     if (hrec) MsiCloseHandle(hrec);
3061
3062     /* check the validity of the table with a deleted row */
3063     hrec = 0;
3064     query = "select * from `MOO`";
3065     r = MsiDatabaseOpenView(hdb, query, &hview);
3066     ok(r == ERROR_SUCCESS, "open view failed\n");
3067
3068     r = MsiViewExecute(hview, 0);
3069     ok(r == ERROR_SUCCESS, "view execute failed\n");
3070
3071     r = MsiViewFetch(hview, &hrec);
3072     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3073
3074     r = MsiRecordGetInteger(hrec, 1);
3075     ok(r == 1, "Expected 1, got %d\n", r);
3076
3077     sz = sizeof buffer;
3078     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3079     ok(r == ERROR_SUCCESS, "record get string failed\n");
3080     ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3081
3082     r = MsiRecordGetInteger(hrec, 3);
3083     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3084
3085     r = MsiRecordGetInteger(hrec, 4);
3086     ok(r == 5, "Expected 5, got %d\n", r);
3087
3088     MsiCloseHandle(hrec);
3089
3090     r = MsiViewFetch(hview, &hrec);
3091     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3092
3093     r = MsiRecordGetInteger(hrec, 1);
3094     ok(r == 2, "Expected 2, got %d\n", r);
3095
3096     sz = sizeof buffer;
3097     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3098     ok(r == ERROR_SUCCESS, "record get string failed\n");
3099     ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3100
3101     r = MsiRecordGetInteger(hrec, 3);
3102     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3103
3104     r = MsiRecordGetInteger(hrec, 4);
3105     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3106
3107     MsiCloseHandle(hrec);
3108
3109     r = MsiViewFetch(hview, &hrec);
3110     ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3111
3112     MsiCloseHandle(hrec);
3113     MsiViewClose(hview);
3114     MsiCloseHandle(hview);
3115
3116     /* check that the property was added */
3117     hpkg = package_from_db(hdb);
3118     ok(hpkg != 0, "Expected non-NULL hpkg\n");
3119
3120     sz = MAX_PATH;
3121     r = MsiGetProperty(hpkg, "prop", buffer, &sz);
3122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3123     ok(!lstrcmp(buffer, "val"), "Expected val, got %s\n", buffer);
3124
3125     MsiCloseHandle(hpkg);
3126     MsiCloseHandle(hdb);
3127
3128     DeleteFile(msifile);
3129     DeleteFile(mstfile);
3130 }
3131
3132 struct join_res
3133 {
3134     const CHAR one[MAX_PATH];
3135     const CHAR two[MAX_PATH];
3136 };
3137
3138 struct join_res_4col
3139 {
3140     const CHAR one[MAX_PATH];
3141     const CHAR two[MAX_PATH];
3142     const CHAR three[MAX_PATH];
3143     const CHAR four[MAX_PATH];
3144 };
3145
3146 struct join_res_uint
3147 {
3148     UINT one;
3149     UINT two;
3150     UINT three;
3151     UINT four;
3152     UINT five;
3153     UINT six;
3154 };
3155
3156 static const struct join_res join_res_first[] =
3157 {
3158     { "alveolar", "procerus" },
3159     { "septum", "procerus" },
3160     { "septum", "nasalis" },
3161     { "ramus", "nasalis" },
3162     { "malar", "mentalis" },
3163 };
3164
3165 static const struct join_res join_res_second[] =
3166 {
3167     { "nasal", "septum" },
3168     { "mandible", "ramus" },
3169 };
3170
3171 static const struct join_res join_res_third[] =
3172 {
3173     { "msvcp.dll", "abcdefgh" },
3174     { "msvcr.dll", "ijklmnop" },
3175 };
3176
3177 static const struct join_res join_res_fourth[] =
3178 {
3179     { "msvcp.dll.01234", "single.dll.31415" },
3180 };
3181
3182 static const struct join_res join_res_fifth[] =
3183 {
3184     { "malar", "procerus" },
3185 };
3186
3187 static const struct join_res join_res_sixth[] =
3188 {
3189     { "malar", "procerus" },
3190     { "malar", "procerus" },
3191     { "malar", "nasalis" },
3192     { "malar", "nasalis" },
3193     { "malar", "nasalis" },
3194     { "malar", "mentalis" },
3195 };
3196
3197 static const struct join_res join_res_seventh[] =
3198 {
3199     { "malar", "nasalis" },
3200     { "malar", "nasalis" },
3201     { "malar", "nasalis" },
3202 };
3203
3204 static const struct join_res_4col join_res_eighth[] =
3205 {
3206     { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3207     { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3208     { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3209     { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3210     { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3211     { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3212 };
3213
3214 static const struct join_res_uint join_res_ninth[] =
3215 {
3216     { 1, 2, 3, 4, 7, 8 },
3217     { 1, 2, 5, 6, 7, 8 },
3218     { 1, 2, 3, 4, 9, 10 },
3219     { 1, 2, 5, 6, 9, 10 },
3220     { 1, 2, 3, 4, 11, 12 },
3221     { 1, 2, 5, 6, 11, 12 },
3222 };
3223
3224 static void test_join(void)
3225 {
3226     MSIHANDLE hdb, hview, hrec;
3227     LPCSTR query;
3228     CHAR buf[MAX_PATH];
3229     UINT r, count;
3230     DWORD size, i;
3231     BOOL data_correct;
3232
3233     hdb = create_db();
3234     ok( hdb, "failed to create db\n");
3235
3236     r = create_component_table( hdb );
3237     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3238
3239     r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3240     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3241
3242     r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3243     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3244
3245     r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3246     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3247
3248     r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3249     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3250
3251     r = create_feature_components_table( hdb );
3252     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3253
3254     r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3255     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3256
3257     r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3258     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3259
3260     r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3261     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3262
3263     r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3264     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3265
3266     r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3267     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3268
3269     r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3270     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3271
3272     r = create_std_dlls_table( hdb );
3273     ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3274
3275     r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3276     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3277
3278     r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3279     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3280
3281     r = create_binary_table( hdb );
3282     ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3283
3284     r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3285     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3286
3287     r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3288     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3289
3290     r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3291     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3292
3293     query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3294     r = run_query( hdb, 0, query);
3295     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3296
3297     query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3298     r = run_query( hdb, 0, query);
3299     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3300
3301     query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3302     r = run_query( hdb, 0, query);
3303     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3304
3305     query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3306     r = run_query( hdb, 0, query);
3307     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3308
3309     query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3310     r = run_query( hdb, 0, query);
3311     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3312
3313     query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3314     r = run_query( hdb, 0, query);
3315     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3316
3317     query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3318     r = run_query( hdb, 0, query);
3319     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3320
3321     query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3322     r = run_query( hdb, 0, query);
3323     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3324
3325     query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3326     r = run_query( hdb, 0, query);
3327     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3328
3329     query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3330     r = run_query( hdb, 0, query);
3331     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3332
3333     query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3334     r = run_query( hdb, 0, query);
3335     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3336
3337     query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3338     r = run_query( hdb, 0, query);
3339     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3340
3341     query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3342     r = run_query( hdb, 0, query);
3343     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3344
3345     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3346             "FROM `Component`, `FeatureComponents` "
3347             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3348             "ORDER BY `Feature_`";
3349     r = MsiDatabaseOpenView(hdb, query, &hview);
3350     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3351
3352     r = MsiViewExecute(hview, 0);
3353     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3354
3355     i = 0;
3356     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3357     {
3358         count = MsiRecordGetFieldCount( hrec );
3359         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3360
3361         size = MAX_PATH;
3362         r = MsiRecordGetString( hrec, 1, buf, &size );
3363         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3364         ok( !lstrcmp( buf, join_res_first[i].one ),
3365             "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3366
3367         size = MAX_PATH;
3368         r = MsiRecordGetString( hrec, 2, buf, &size );
3369         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3370         ok( !lstrcmp( buf, join_res_first[i].two ),
3371             "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3372
3373         i++;
3374         MsiCloseHandle(hrec);
3375     }
3376
3377     ok( i == 5, "Expected 5 rows, got %d\n", i );
3378     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3379
3380     MsiViewClose(hview);
3381     MsiCloseHandle(hview);
3382
3383     /* try a join without a WHERE condition */
3384     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3385             "FROM `Component`, `FeatureComponents` ";
3386     r = MsiDatabaseOpenView(hdb, query, &hview);
3387     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3388
3389     r = MsiViewExecute(hview, 0);
3390     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3391
3392     i = 0;
3393     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3394     {
3395         i++;
3396         MsiCloseHandle(hrec);
3397     }
3398     ok( i == 24, "Expected 24 rows, got %d\n", i );
3399
3400     MsiViewClose(hview);
3401     MsiCloseHandle(hview);
3402
3403     query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3404             "WHERE FeatureComponents.Component_=Component.Component "
3405             "AND (Feature_='nasalis') ORDER BY Feature_";
3406     r = MsiDatabaseOpenView(hdb, query, &hview);
3407     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3408
3409     r = MsiViewExecute(hview, 0);
3410     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3411
3412     i = 0;
3413     data_correct = TRUE;
3414     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3415     {
3416         count = MsiRecordGetFieldCount( hrec );
3417         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3418
3419         size = MAX_PATH;
3420         r = MsiRecordGetString( hrec, 1, buf, &size );
3421         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3422         if( lstrcmp( buf, join_res_second[i].one ))
3423             data_correct = FALSE;
3424
3425         size = MAX_PATH;
3426         r = MsiRecordGetString( hrec, 2, buf, &size );
3427         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3428         if( lstrcmp( buf, join_res_second[i].two ))
3429             data_correct = FALSE;
3430
3431         i++;
3432         MsiCloseHandle(hrec);
3433     }
3434
3435     ok( data_correct, "data returned in the wrong order\n");
3436
3437     ok( i == 2, "Expected 2 rows, got %d\n", i );
3438     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3439
3440     MsiViewClose(hview);
3441     MsiCloseHandle(hview);
3442
3443     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3444             "FROM `StdDlls`, `Binary` "
3445             "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3446             "ORDER BY `File`";
3447     r = MsiDatabaseOpenView(hdb, query, &hview);
3448     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3449
3450     r = MsiViewExecute(hview, 0);
3451     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3452
3453     i = 0;
3454     data_correct = TRUE;
3455     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3456     {
3457         count = MsiRecordGetFieldCount( hrec );
3458         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3459
3460         size = MAX_PATH;
3461         r = MsiRecordGetString( hrec, 1, buf, &size );
3462         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3463         if( lstrcmp( buf, join_res_third[i].one ) )
3464             data_correct = FALSE;
3465
3466         size = MAX_PATH;
3467         r = MsiRecordGetString( hrec, 2, buf, &size );
3468         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3469         if( lstrcmp( buf, join_res_third[i].two ) )
3470             data_correct = FALSE;
3471
3472         i++;
3473         MsiCloseHandle(hrec);
3474     }
3475     ok( data_correct, "data returned in the wrong order\n");
3476
3477     ok( i == 2, "Expected 2 rows, got %d\n", i );
3478
3479     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3480
3481     MsiViewClose(hview);
3482     MsiCloseHandle(hview);
3483
3484     query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3485             "FROM `StdDlls`, `Binary` "
3486             "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3487             "ORDER BY `Name`";
3488     r = MsiDatabaseOpenView(hdb, query, &hview);
3489     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3490
3491     r = MsiViewExecute(hview, 0);
3492     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3493
3494     i = 0;
3495     data_correct = TRUE;
3496     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3497     {
3498         count = MsiRecordGetFieldCount( hrec );
3499         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3500
3501         size = MAX_PATH;
3502         r = MsiRecordGetString( hrec, 1, buf, &size );
3503         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3504         if( lstrcmp( buf, join_res_fourth[i].one ))
3505             data_correct = FALSE;
3506
3507         size = MAX_PATH;
3508         r = MsiRecordGetString( hrec, 2, buf, &size );
3509         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3510         if( lstrcmp( buf, join_res_fourth[i].two ))
3511             data_correct = FALSE;
3512
3513         i++;
3514         MsiCloseHandle(hrec);
3515     }
3516     ok( data_correct, "data returned in the wrong order\n");
3517
3518     ok( i == 1, "Expected 1 rows, got %d\n", i );
3519     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3520
3521     MsiViewClose(hview);
3522     MsiCloseHandle(hview);
3523
3524     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3525             "FROM `Component`, `FeatureComponents` "
3526             "WHERE `Component`.`Component` = 'zygomatic' "
3527             "AND `FeatureComponents`.`Component_` = 'maxilla' "
3528             "ORDER BY `Feature_`";
3529     r = MsiDatabaseOpenView(hdb, query, &hview);
3530     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3531
3532     r = MsiViewExecute(hview, 0);
3533     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3534
3535     i = 0;
3536     data_correct = TRUE;
3537     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3538     {
3539         count = MsiRecordGetFieldCount( hrec );
3540         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3541
3542         size = MAX_PATH;
3543         r = MsiRecordGetString( hrec, 1, buf, &size );
3544         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3545         if( lstrcmp( buf, join_res_fifth[i].one ))
3546             data_correct = FALSE;
3547
3548         size = MAX_PATH;
3549         r = MsiRecordGetString( hrec, 2, buf, &size );
3550         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3551         if( lstrcmp( buf, join_res_fifth[i].two ))
3552             data_correct = FALSE;
3553
3554         i++;
3555         MsiCloseHandle(hrec);
3556     }
3557     ok( data_correct, "data returned in the wrong order\n");
3558
3559     ok( i == 1, "Expected 1 rows, got %d\n", i );
3560     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3561
3562     MsiViewClose(hview);
3563     MsiCloseHandle(hview);
3564
3565     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3566             "FROM `Component`, `FeatureComponents` "
3567             "WHERE `Component` = 'zygomatic' "
3568             "ORDER BY `Feature_`";
3569     r = MsiDatabaseOpenView(hdb, query, &hview);
3570     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3571
3572     r = MsiViewExecute(hview, 0);
3573     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3574
3575     i = 0;
3576     data_correct = TRUE;
3577     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3578     {
3579         count = MsiRecordGetFieldCount( hrec );
3580         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3581
3582         size = MAX_PATH;
3583         r = MsiRecordGetString( hrec, 1, buf, &size );
3584         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3585         if( lstrcmp( buf, join_res_sixth[i].one ))
3586             data_correct = FALSE;
3587
3588         size = MAX_PATH;
3589         r = MsiRecordGetString( hrec, 2, buf, &size );
3590         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3591         if( lstrcmp( buf, join_res_sixth[i].two ))
3592             data_correct = FALSE;
3593
3594         i++;
3595         MsiCloseHandle(hrec);
3596     }
3597     ok( data_correct, "data returned in the wrong order\n");
3598
3599     ok( i == 6, "Expected 6 rows, got %d\n", i );
3600     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3601
3602     MsiViewClose(hview);
3603     MsiCloseHandle(hview);
3604
3605     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3606             "FROM `Component`, `FeatureComponents` "
3607             "WHERE `Component` = 'zygomatic' "
3608             "AND `Feature_` = 'nasalis' "
3609             "ORDER BY `Feature_`";
3610     r = MsiDatabaseOpenView(hdb, query, &hview);
3611     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3612
3613     r = MsiViewExecute(hview, 0);
3614     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3615
3616     i = 0;
3617     data_correct = TRUE;
3618     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3619     {
3620         count = MsiRecordGetFieldCount( hrec );
3621         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3622
3623         size = MAX_PATH;
3624         r = MsiRecordGetString( hrec, 1, buf, &size );
3625         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3626         if( lstrcmp( buf, join_res_seventh[i].one ))
3627             data_correct = FALSE;
3628
3629         size = MAX_PATH;
3630         r = MsiRecordGetString( hrec, 2, buf, &size );
3631         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3632         if( lstrcmp( buf, join_res_seventh[i].two ))
3633             data_correct = FALSE;
3634
3635         i++;
3636         MsiCloseHandle(hrec);
3637     }
3638
3639     ok( data_correct, "data returned in the wrong order\n");
3640     ok( i == 3, "Expected 3 rows, got %d\n", i );
3641     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3642
3643     MsiViewClose(hview);
3644     MsiCloseHandle(hview);
3645
3646     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3647             "FROM `StdDlls`, `Binary` ";
3648     r = MsiDatabaseOpenView(hdb, query, &hview);
3649     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3650
3651     r = MsiViewExecute(hview, 0);
3652     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3653
3654     i = 0;
3655     data_correct = TRUE;
3656     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3657     {
3658         count = MsiRecordGetFieldCount( hrec );
3659         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3660
3661         size = MAX_PATH;
3662         r = MsiRecordGetString( hrec, 1, buf, &size );
3663         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3664         if( lstrcmp( buf, join_res_eighth[i].one ))
3665             data_correct = FALSE;
3666
3667         size = MAX_PATH;
3668         r = MsiRecordGetString( hrec, 2, buf, &size );
3669         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3670         if( lstrcmp( buf, join_res_eighth[i].four ))
3671             data_correct = FALSE;
3672
3673         i++;
3674         MsiCloseHandle(hrec);
3675     }
3676
3677     ok( data_correct, "data returned in the wrong order\n");
3678     ok( i == 6, "Expected 6 rows, got %d\n", i );
3679     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3680
3681     MsiViewClose(hview);
3682     MsiCloseHandle(hview);
3683
3684     query = "SELECT * FROM `StdDlls`, `Binary` ";
3685     r = MsiDatabaseOpenView(hdb, query, &hview);
3686     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3687
3688     r = MsiViewExecute(hview, 0);
3689     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3690
3691     i = 0;
3692     data_correct = TRUE;
3693     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3694     {
3695         count = MsiRecordGetFieldCount( hrec );
3696         ok( count == 4, "Expected 4 record fields, got %d\n", count );
3697
3698         size = MAX_PATH;
3699         r = MsiRecordGetString( hrec, 1, buf, &size );
3700         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3701         if( lstrcmp( buf, join_res_eighth[i].one ))
3702             data_correct = FALSE;
3703
3704         size = MAX_PATH;
3705         r = MsiRecordGetString( hrec, 2, buf, &size );
3706         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3707         if( lstrcmp( buf, join_res_eighth[i].two ))
3708             data_correct = FALSE;
3709
3710         size = MAX_PATH;
3711         r = MsiRecordGetString( hrec, 3, buf, &size );
3712         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3713         if( lstrcmp( buf, join_res_eighth[i].three ))
3714             data_correct = FALSE;
3715
3716         size = MAX_PATH;
3717         r = MsiRecordGetString( hrec, 4, buf, &size );
3718         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3719         if( lstrcmp( buf, join_res_eighth[i].four ))
3720             data_correct = FALSE;
3721
3722         i++;
3723         MsiCloseHandle(hrec);
3724     }
3725     ok( data_correct, "data returned in the wrong order\n");
3726
3727     ok( i == 6, "Expected 6 rows, got %d\n", i );
3728     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3729
3730     MsiViewClose(hview);
3731     MsiCloseHandle(hview);
3732
3733     query = "SELECT * FROM `One`, `Two`, `Three` ";
3734     r = MsiDatabaseOpenView(hdb, query, &hview);
3735     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3736
3737     r = MsiViewExecute(hview, 0);
3738     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3739
3740     i = 0;
3741     data_correct = TRUE;
3742     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3743     {
3744         count = MsiRecordGetFieldCount( hrec );
3745         ok( count == 6, "Expected 6 record fields, got %d\n", count );
3746
3747         r = MsiRecordGetInteger( hrec, 1 );
3748         if( r != join_res_ninth[i].one )
3749             data_correct = FALSE;
3750
3751         r = MsiRecordGetInteger( hrec, 2 );
3752         if( r != join_res_ninth[i].two )
3753             data_correct = FALSE;
3754
3755         r = MsiRecordGetInteger( hrec, 3 );
3756         if( r != join_res_ninth[i].three )
3757             data_correct = FALSE;
3758
3759         r = MsiRecordGetInteger( hrec, 4 );
3760         if( r != join_res_ninth[i].four )
3761             data_correct = FALSE;
3762
3763         r = MsiRecordGetInteger( hrec, 5 );
3764         if( r != join_res_ninth[i].five )
3765             data_correct = FALSE;
3766
3767         r = MsiRecordGetInteger( hrec, 6);
3768         if( r != join_res_ninth[i].six )
3769             data_correct = FALSE;
3770
3771         i++;
3772         MsiCloseHandle(hrec);
3773     }
3774     ok( data_correct, "data returned in the wrong order\n");
3775
3776     ok( i == 6, "Expected 6 rows, got %d\n", i );
3777     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3778
3779     MsiViewClose(hview);
3780     MsiCloseHandle(hview);
3781
3782     query = "SELECT * FROM `Four`, `Five`";
3783     r = MsiDatabaseOpenView(hdb, query, &hview);
3784     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3785
3786     r = MsiViewExecute(hview, 0);
3787     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3788
3789     r = MsiViewFetch(hview, &hrec);
3790     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3791
3792     MsiViewClose(hview);
3793     MsiCloseHandle(hview);
3794
3795     query = "SELECT * FROM `Nonexistent`, `One`";
3796     r = MsiDatabaseOpenView(hdb, query, &hview);
3797     ok( r == ERROR_BAD_QUERY_SYNTAX,
3798         "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3799
3800     /* try updating a row in a join table */
3801     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3802             "FROM `Component`, `FeatureComponents` "
3803             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3804             "ORDER BY `Feature_`";
3805     r = MsiDatabaseOpenView(hdb, query, &hview);
3806     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3807
3808     r = MsiViewExecute(hview, 0);
3809     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3810
3811     r = MsiViewFetch(hview, &hrec);
3812     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3813
3814     r = MsiRecordSetString( hrec, 1, "epicranius" );
3815     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3816
3817     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3818     ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3819
3820     /* try another valid operation for joins */
3821     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3822     todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3823
3824     /* try an invalid operation for joins */
3825     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3826     ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3827
3828     r = MsiRecordSetString( hrec, 2, "epicranius" );
3829     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3830
3831     /* primary key cannot be updated */
3832     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3833     todo_wine ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3834
3835     MsiCloseHandle(hrec);
3836     MsiViewClose(hview);
3837     MsiCloseHandle(hview);
3838
3839     r = MsiDatabaseOpenView(hdb, query, &hview);
3840     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3841
3842     r = MsiViewExecute(hview, 0);
3843     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3844
3845     r = MsiViewFetch(hview, &hrec);
3846     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3847
3848     size = MAX_PATH;
3849     r = MsiRecordGetString( hrec, 1, buf, &size );
3850     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3851     ok( !lstrcmp( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
3852
3853     MsiCloseHandle(hrec);
3854     MsiViewClose(hview);
3855     MsiCloseHandle(hview);
3856
3857     MsiCloseHandle(hdb);
3858     DeleteFile(msifile);
3859 }
3860
3861 static void test_temporary_table(void)
3862 {
3863     MSICONDITION cond;
3864     MSIHANDLE hdb = 0, view = 0, rec;
3865     const char *query;
3866     UINT r;
3867     char buf[0x10];
3868     DWORD sz;
3869
3870     cond = MsiDatabaseIsTablePersistent(0, NULL);
3871     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3872
3873     hdb = create_db();
3874     ok( hdb, "failed to create db\n");
3875
3876     cond = MsiDatabaseIsTablePersistent(hdb, NULL);
3877     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3878
3879     cond = MsiDatabaseIsTablePersistent(hdb, "_Tables");
3880     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3881
3882     cond = MsiDatabaseIsTablePersistent(hdb, "_Columns");
3883     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3884
3885     cond = MsiDatabaseIsTablePersistent(hdb, "_Storages");
3886     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3887
3888     cond = MsiDatabaseIsTablePersistent(hdb, "_Streams");
3889     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3890
3891     query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
3892     r = run_query(hdb, 0, query);
3893     ok(r == ERROR_SUCCESS, "failed to add table\n");
3894
3895     cond = MsiDatabaseIsTablePersistent(hdb, "P");
3896     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3897
3898     query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
3899     r = run_query(hdb, 0, query);
3900     ok(r == ERROR_SUCCESS, "failed to add table\n");
3901
3902     cond = MsiDatabaseIsTablePersistent(hdb, "P2");
3903     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3904
3905     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
3906     r = run_query(hdb, 0, query);
3907     ok(r == ERROR_SUCCESS, "failed to add table\n");
3908
3909     cond = MsiDatabaseIsTablePersistent(hdb, "T");
3910     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
3911
3912     query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3913     r = run_query(hdb, 0, query);
3914     ok(r == ERROR_SUCCESS, "failed to add table\n");
3915
3916     query = "SELECT * FROM `T2`";
3917     r = MsiDatabaseOpenView(hdb, query, &view);
3918     ok(r == ERROR_BAD_QUERY_SYNTAX,
3919        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3920
3921     cond = MsiDatabaseIsTablePersistent(hdb, "T2");
3922     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3923
3924     query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
3925     r = run_query(hdb, 0, query);
3926     ok(r == ERROR_SUCCESS, "failed to add table\n");
3927
3928     cond = MsiDatabaseIsTablePersistent(hdb, "T3");
3929     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3930
3931     query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3932     r = run_query(hdb, 0, query);
3933     ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
3934
3935     cond = MsiDatabaseIsTablePersistent(hdb, "T4");
3936     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3937
3938     query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
3939     r = run_query(hdb, 0, query);
3940     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
3941
3942     query = "select * from `T`";
3943     r = MsiDatabaseOpenView(hdb, query, &view);
3944     ok(r == ERROR_SUCCESS, "failed to query table\n");
3945     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
3946     ok(r == ERROR_SUCCESS, "failed to get column info\n");
3947
3948     sz = sizeof buf;
3949     r = MsiRecordGetString(rec, 1, buf, &sz);
3950     ok(r == ERROR_SUCCESS, "failed to get string\n");
3951     ok( 0 == strcmp("G255", buf), "wrong column type\n");
3952
3953     sz = sizeof buf;
3954     r = MsiRecordGetString(rec, 2, buf, &sz);
3955     ok(r == ERROR_SUCCESS, "failed to get string\n");
3956     ok( 0 == strcmp("j2", buf), "wrong column type\n");
3957
3958     MsiCloseHandle( rec );
3959     MsiViewClose( view );
3960     MsiCloseHandle( view );
3961
3962     /* query the table data */
3963     rec = 0;
3964     r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
3965     ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
3966     MsiCloseHandle( rec );
3967
3968     /* query the column data */
3969     rec = 0;
3970     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
3971     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
3972     if (rec) MsiCloseHandle( rec );
3973
3974     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
3975     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
3976     if (rec) MsiCloseHandle( rec );
3977
3978     MsiCloseHandle( hdb );
3979
3980     DeleteFile(msifile);
3981 }
3982
3983 static void test_alter(void)
3984 {
3985     MSICONDITION cond;
3986     MSIHANDLE hdb = 0;
3987     const char *query;
3988     UINT r;
3989
3990     hdb = create_db();
3991     ok( hdb, "failed to create db\n");
3992
3993     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
3994     r = run_query(hdb, 0, query);
3995     ok(r == ERROR_SUCCESS, "failed to add table\n");
3996
3997     cond = MsiDatabaseIsTablePersistent(hdb, "T");
3998     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
3999
4000     query = "ALTER TABLE `T` HOLD";
4001     r = run_query(hdb, 0, query);
4002     ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4003
4004     query = "ALTER TABLE `T` FREE";
4005     r = run_query(hdb, 0, query);
4006     ok(r == ERROR_SUCCESS, "failed to free table\n");
4007
4008     query = "ALTER TABLE `T` FREE";
4009     r = run_query(hdb, 0, query);
4010     ok(r == ERROR_SUCCESS, "failed to free table\n");
4011
4012     query = "ALTER TABLE `T` FREE";
4013     r = run_query(hdb, 0, query);
4014     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4015
4016     query = "ALTER TABLE `T` HOLD";
4017     r = run_query(hdb, 0, query);
4018     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4019
4020     /* table T is removed */
4021     query = "SELECT * FROM `T`";
4022     r = run_query(hdb, 0, query);
4023     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4024
4025     /* create the table again */
4026     query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4027     r = run_query(hdb, 0, query);
4028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4029
4030     /* up the ref count */
4031     query = "ALTER TABLE `U` HOLD";
4032     r = run_query(hdb, 0, query);
4033     ok(r == ERROR_SUCCESS, "failed to free table\n");
4034
4035     /* add column, no data type */
4036     query = "ALTER TABLE `U` ADD `C`";
4037     r = run_query(hdb, 0, query);
4038     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4039
4040     query = "ALTER TABLE `U` ADD `C` INTEGER";
4041     r = run_query(hdb, 0, query);
4042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4043
4044     /* add column C again */
4045     query = "ALTER TABLE `U` ADD `C` INTEGER";
4046     r = run_query(hdb, 0, query);
4047     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4048
4049     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4050     r = run_query(hdb, 0, query);
4051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4052
4053     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4054     r = run_query(hdb, 0, query);
4055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4056
4057     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4058     r = run_query(hdb, 0, query);
4059     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4060
4061     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4062     r = run_query(hdb, 0, query);
4063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4064
4065     query = "SELECT * FROM `U` WHERE `D` = 8";
4066     r = run_query(hdb, 0, query);
4067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4068
4069     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4070     r = run_query(hdb, 0, query);
4071     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4072
4073     query = "ALTER COLUMN `D` FREE";
4074     r = run_query(hdb, 0, query);
4075     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4076
4077     /* drop the ref count */
4078     query = "ALTER TABLE `U` FREE";
4079     r = run_query(hdb, 0, query);
4080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4081
4082     /* table is not empty */
4083     query = "SELECT * FROM `U`";
4084     r = run_query(hdb, 0, query);
4085     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4086
4087     /* column D is removed */
4088     query = "SELECT * FROM `U` WHERE `D` = 8";
4089     r = run_query(hdb, 0, query);
4090     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4091
4092     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4093     r = run_query(hdb, 0, query);
4094     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4095
4096     /* add the column again */
4097     query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4098     r = run_query(hdb, 0, query);
4099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4100
4101     /* up the ref count */
4102     query = "ALTER TABLE `U` HOLD";
4103     r = run_query(hdb, 0, query);
4104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4105
4106     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4107     r = run_query(hdb, 0, query);
4108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4109
4110     query = "SELECT * FROM `U` WHERE `E` = 16";
4111     r = run_query(hdb, 0, query);
4112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4113
4114     /* drop the ref count */
4115     query = "ALTER TABLE `U` FREE";
4116     r = run_query(hdb, 0, query);
4117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4118
4119     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4120     r = run_query(hdb, 0, query);
4121     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4122
4123     query = "SELECT * FROM `U` WHERE `E` = 20";
4124     r = run_query(hdb, 0, query);
4125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4126
4127     /* drop the ref count */
4128     query = "ALTER TABLE `U` FREE";
4129     r = run_query(hdb, 0, query);
4130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4131
4132     /* table still exists */
4133     query = "SELECT * FROM `U`";
4134     r = run_query(hdb, 0, query);
4135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4136
4137     /* col E is removed */
4138     query = "SELECT * FROM `U` WHERE `E` = 20";
4139     r = run_query(hdb, 0, query);
4140     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4141
4142     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4143     r = run_query(hdb, 0, query);
4144     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4145
4146     /* drop the ref count once more */
4147     query = "ALTER TABLE `U` FREE";
4148     r = run_query(hdb, 0, query);
4149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4150
4151     /* table still exists */
4152     query = "SELECT * FROM `U`";
4153     r = run_query(hdb, 0, query);
4154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4155
4156     MsiCloseHandle( hdb );
4157     DeleteFile(msifile);
4158 }
4159
4160 static void test_integers(void)
4161 {
4162     MSIHANDLE hdb = 0, view = 0, rec = 0;
4163     DWORD count, i;
4164     const char *query;
4165     UINT r;
4166
4167     /* just MsiOpenDatabase should not create a file */
4168     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4169     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4170
4171     /* create a table */
4172     query = "CREATE TABLE `integers` ( "
4173             "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4174             "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4175             "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4176             "PRIMARY KEY `one`)";
4177     r = MsiDatabaseOpenView(hdb, query, &view);
4178     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4179     r = MsiViewExecute(view, 0);
4180     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4181     r = MsiViewClose(view);
4182     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4183     r = MsiCloseHandle(view);
4184     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4185
4186     query = "SELECT * FROM `integers`";
4187     r = MsiDatabaseOpenView(hdb, query, &view);
4188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4189
4190     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4191     count = MsiRecordGetFieldCount(rec);
4192     ok(count == 8, "Expected 8, got %d\n", count);
4193     ok(check_record(rec, 1, "one"), "Expected one\n");
4194     ok(check_record(rec, 2, "two"), "Expected two\n");
4195     ok(check_record(rec, 3, "three"), "Expected three\n");
4196     ok(check_record(rec, 4, "four"), "Expected four\n");
4197     ok(check_record(rec, 5, "five"), "Expected five\n");
4198     ok(check_record(rec, 6, "six"), "Expected six\n");
4199     ok(check_record(rec, 7, "seven"), "Expected seven\n");
4200     ok(check_record(rec, 8, "eight"), "Expected eight\n");
4201     MsiCloseHandle(rec);
4202
4203     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4204     count = MsiRecordGetFieldCount(rec);
4205     ok(count == 8, "Expected 8, got %d\n", count);
4206     ok(check_record(rec, 1, "I2"), "Expected I2\n");
4207     ok(check_record(rec, 2, "I2"), "Expected I2\n");
4208     ok(check_record(rec, 3, "I2"), "Expected I2\n");
4209     ok(check_record(rec, 4, "I4"), "Expected I4\n");
4210     ok(check_record(rec, 5, "i2"), "Expected i2\n");
4211     ok(check_record(rec, 6, "i2"), "Expected i2\n");
4212     ok(check_record(rec, 7, "i2"), "Expected i2\n");
4213     ok(check_record(rec, 8, "i4"), "Expected i4\n");
4214     MsiCloseHandle(rec);
4215
4216     MsiViewClose(view);
4217     MsiCloseHandle(view);
4218
4219     /* insert values into it, NULL where NOT NULL is specified */
4220     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4221         "VALUES('', '', '', '', '', '', '', '')";
4222     r = MsiDatabaseOpenView(hdb, query, &view);
4223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4224     r = MsiViewExecute(view, 0);
4225     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4226
4227     MsiViewClose(view);
4228     MsiCloseHandle(view);
4229
4230     query = "SELECT * FROM `integers`";
4231     r = do_query(hdb, query, &rec);
4232     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4233
4234     r = MsiRecordGetFieldCount(rec);
4235     ok(r == -1, "record count wrong: %d\n", r);
4236
4237     MsiCloseHandle(rec);
4238
4239     /* insert legitimate values into it */
4240     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4241         "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4242     r = MsiDatabaseOpenView(hdb, query, &view);
4243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4244     r = MsiViewExecute(view, 0);
4245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4246
4247     query = "SELECT * FROM `integers`";
4248     r = do_query(hdb, query, &rec);
4249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4250
4251     r = MsiRecordGetFieldCount(rec);
4252     ok(r == 8, "record count wrong: %d\n", r);
4253
4254     i = MsiRecordGetInteger(rec, 1);
4255     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4256     i = MsiRecordGetInteger(rec, 3);
4257     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4258     i = MsiRecordGetInteger(rec, 2);
4259     ok(i == 2, "Expected 2, got %d\n", i);
4260     i = MsiRecordGetInteger(rec, 4);
4261     ok(i == 4, "Expected 4, got %d\n", i);
4262     i = MsiRecordGetInteger(rec, 5);
4263     ok(i == 5, "Expected 5, got %d\n", i);
4264     i = MsiRecordGetInteger(rec, 6);
4265     ok(i == 6, "Expected 6, got %d\n", i);
4266     i = MsiRecordGetInteger(rec, 7);
4267     ok(i == 7, "Expected 7, got %d\n", i);
4268     i = MsiRecordGetInteger(rec, 8);
4269     ok(i == 8, "Expected 8, got %d\n", i);
4270
4271     MsiCloseHandle(rec);
4272     MsiViewClose(view);
4273     MsiCloseHandle(view);
4274
4275     r = MsiDatabaseCommit(hdb);
4276     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4277
4278     r = MsiCloseHandle(hdb);
4279     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4280
4281     r = DeleteFile(msifile);
4282     ok(r == TRUE, "file didn't exist after commit\n");
4283 }
4284
4285 static void test_update(void)
4286 {
4287     MSIHANDLE hdb = 0, view = 0, rec = 0;
4288     CHAR result[MAX_PATH];
4289     const char *query;
4290     DWORD size;
4291     UINT r;
4292
4293     /* just MsiOpenDatabase should not create a file */
4294     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4295     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4296
4297     /* create the Control table */
4298     query = "CREATE TABLE `Control` ( "
4299         "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4300         "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4301         "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4302         "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4303     r = MsiDatabaseOpenView(hdb, query, &view);
4304     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4305     r = MsiViewExecute(view, 0);
4306     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4307     r = MsiViewClose(view);
4308     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4309     r = MsiCloseHandle(view);
4310     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4311
4312     /* add a control */
4313     query = "INSERT INTO `Control` ( "
4314         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4315         "`Property`, `Text`, `Control_Next`, `Help` )"
4316         "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4317     r = MsiDatabaseOpenView(hdb, query, &view);
4318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4319     r = MsiViewExecute(view, 0);
4320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4321     r = MsiViewClose(view);
4322     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4323     r = MsiCloseHandle(view);
4324     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4325
4326     /* add a second control */
4327     query = "INSERT INTO `Control` ( "
4328         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4329         "`Property`, `Text`, `Control_Next`, `Help` )"
4330         "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4331     r = MsiDatabaseOpenView(hdb, query, &view);
4332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4333     r = MsiViewExecute(view, 0);
4334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4335     r = MsiViewClose(view);
4336     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4337     r = MsiCloseHandle(view);
4338     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4339
4340     /* add a third control */
4341     query = "INSERT INTO `Control` ( "
4342         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4343         "`Property`, `Text`, `Control_Next`, `Help` )"
4344         "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4345     r = MsiDatabaseOpenView(hdb, query, &view);
4346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4347     r = MsiViewExecute(view, 0);
4348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4349     r = MsiViewClose(view);
4350     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4351     r = MsiCloseHandle(view);
4352     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4353
4354     /* bad table */
4355     query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4356     r = MsiDatabaseOpenView(hdb, query, &view);
4357     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4358
4359     /* bad set column */
4360     query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4361     r = MsiDatabaseOpenView(hdb, query, &view);
4362     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4363
4364     /* bad where condition */
4365     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4366     r = MsiDatabaseOpenView(hdb, query, &view);
4367     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4368
4369     /* just the dialog_ specified */
4370     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4371     r = MsiDatabaseOpenView(hdb, query, &view);
4372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4373     r = MsiViewExecute(view, 0);
4374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4375     r = MsiViewClose(view);
4376     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4377     r = MsiCloseHandle(view);
4378     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4379
4380     /* check the modified text */
4381     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4382     r = MsiDatabaseOpenView(hdb, query, &view);
4383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4384     r = MsiViewExecute(view, 0);
4385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4386
4387     r = MsiViewFetch(view, &rec);
4388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4389
4390     size = MAX_PATH;
4391     r = MsiRecordGetString(rec, 1, result, &size);
4392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4393     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4394
4395     MsiCloseHandle(rec);
4396
4397     r = MsiViewFetch(view, &rec);
4398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4399
4400     size = MAX_PATH;
4401     r = MsiRecordGetString(rec, 1, result, &size);
4402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4403     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4404
4405     MsiCloseHandle(rec);
4406
4407     r = MsiViewFetch(view, &rec);
4408     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4409
4410     r = MsiViewClose(view);
4411     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4412     r = MsiCloseHandle(view);
4413     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4414
4415     /* dialog_ and control specified */
4416     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4417     r = MsiDatabaseOpenView(hdb, query, &view);
4418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4419     r = MsiViewExecute(view, 0);
4420     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4421     r = MsiViewClose(view);
4422     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4423     r = MsiCloseHandle(view);
4424     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4425
4426     /* check the modified text */
4427     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4428     r = MsiDatabaseOpenView(hdb, query, &view);
4429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4430     r = MsiViewExecute(view, 0);
4431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4432
4433     r = MsiViewFetch(view, &rec);
4434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4435
4436     size = MAX_PATH;
4437     r = MsiRecordGetString(rec, 1, result, &size);
4438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4439     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4440
4441     MsiCloseHandle(rec);
4442
4443     r = MsiViewFetch(view, &rec);
4444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4445
4446     size = MAX_PATH;
4447     r = MsiRecordGetString(rec, 1, result, &size);
4448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4449     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4450
4451     MsiCloseHandle(rec);
4452
4453     r = MsiViewFetch(view, &rec);
4454     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4455
4456     r = MsiViewClose(view);
4457     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4458     r = MsiCloseHandle(view);
4459     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4460
4461     /* no where condition */
4462     query = "UPDATE `Control` SET `Text` = 'this is text'";
4463     r = MsiDatabaseOpenView(hdb, query, &view);
4464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4465     r = MsiViewExecute(view, 0);
4466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4467     r = MsiViewClose(view);
4468     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4469     r = MsiCloseHandle(view);
4470     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4471
4472     /* check the modified text */
4473     query = "SELECT `Text` FROM `Control`";
4474     r = MsiDatabaseOpenView(hdb, query, &view);
4475     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4476     r = MsiViewExecute(view, 0);
4477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4478
4479     r = MsiViewFetch(view, &rec);
4480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4481
4482     size = MAX_PATH;
4483     r = MsiRecordGetString(rec, 1, result, &size);
4484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4485     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4486
4487     MsiCloseHandle(rec);
4488
4489     r = MsiViewFetch(view, &rec);
4490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4491
4492     size = MAX_PATH;
4493     r = MsiRecordGetString(rec, 1, result, &size);
4494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4495     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4496
4497     MsiCloseHandle(rec);
4498
4499     r = MsiViewFetch(view, &rec);
4500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4501
4502     size = MAX_PATH;
4503     r = MsiRecordGetString(rec, 1, result, &size);
4504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4505     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4506
4507     MsiCloseHandle(rec);
4508
4509     r = MsiViewFetch(view, &rec);
4510     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4511
4512     r = MsiViewClose(view);
4513     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4514     r = MsiCloseHandle(view);
4515     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4516
4517     query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4518         "`Orange` CHAR(72),  `Pear` INT PRIMARY KEY `Banana`)";
4519     r = run_query(hdb, 0, query);
4520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4521
4522     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4523         "VALUES('one', 'two', 3)";
4524     r = run_query(hdb, 0, query);
4525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4526
4527     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4528         "VALUES('three', 'four', 5)";
4529     r = run_query(hdb, 0, query);
4530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4531
4532     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4533         "VALUES('six', 'two', 7)";
4534     r = run_query(hdb, 0, query);
4535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4536
4537     rec = MsiCreateRecord(2);
4538     MsiRecordSetInteger(rec, 1, 8);
4539     MsiRecordSetString(rec, 2, "two");
4540
4541     query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4542     r = run_query(hdb, rec, query);
4543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4544
4545     MsiCloseHandle(rec);
4546
4547     query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4548     r = MsiDatabaseOpenView(hdb, query, &view);
4549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4550     r = MsiViewExecute(view, 0);
4551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4552
4553     r = MsiViewFetch(view, &rec);
4554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4555
4556     r = MsiRecordGetInteger(rec, 1);
4557     ok(r == 8, "Expected 8, got %d\n", r);
4558
4559     MsiCloseHandle(rec);
4560
4561     r = MsiViewFetch(view, &rec);
4562     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4563
4564     r = MsiRecordGetInteger(rec, 1);
4565     ok(r == 8, "Expected 8, got %d\n", r);
4566
4567     MsiCloseHandle(rec);
4568
4569     r = MsiViewFetch(view, &rec);
4570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4571
4572     r = MsiRecordGetInteger(rec, 1);
4573     ok(r == 5, "Expected 5, got %d\n", r);
4574
4575     MsiCloseHandle(rec);
4576
4577     r = MsiViewFetch(view, &rec);
4578     ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4579
4580     MsiViewClose(view);
4581     MsiCloseHandle(view);
4582
4583     r = MsiDatabaseCommit(hdb);
4584     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4585     r = MsiCloseHandle(hdb);
4586     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4587
4588     DeleteFile(msifile);
4589 }
4590
4591 static void test_special_tables(void)
4592 {
4593     const char *query;
4594     MSIHANDLE hdb = 0;
4595     UINT r;
4596
4597     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4598     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4599
4600     query = "CREATE TABLE `_Properties` ( "
4601         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4602     r = run_query(hdb, 0, query);
4603     ok(r == ERROR_SUCCESS, "failed to create table\n");
4604
4605     query = "CREATE TABLE `_Storages` ( "
4606         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4607     r = run_query(hdb, 0, query);
4608     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4609
4610     query = "CREATE TABLE `_Streams` ( "
4611         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4612     r = run_query(hdb, 0, query);
4613     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4614
4615     query = "CREATE TABLE `_Tables` ( "
4616         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4617     r = run_query(hdb, 0, query);
4618     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4619
4620     query = "CREATE TABLE `_Columns` ( "
4621         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4622     r = run_query(hdb, 0, query);
4623     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4624
4625     r = MsiCloseHandle(hdb);
4626     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4627 }
4628
4629 static void test_tables_order(void)
4630 {
4631     const char *query;
4632     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4633     UINT r;
4634     char buffer[100];
4635     DWORD sz;
4636
4637     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4638     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4639
4640     query = "CREATE TABLE `foo` ( "
4641         "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4642     r = run_query(hdb, 0, query);
4643     ok(r == ERROR_SUCCESS, "failed to create table\n");
4644
4645     query = "CREATE TABLE `bar` ( "
4646         "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4647     r = run_query(hdb, 0, query);
4648     ok(r == ERROR_SUCCESS, "failed to create table\n");
4649
4650     query = "CREATE TABLE `baz` ( "
4651         "`bar` INT NOT NULL, "
4652         "`baz` INT NOT NULL, "
4653         "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4654     r = run_query(hdb, 0, query);
4655     ok(r == ERROR_SUCCESS, "failed to create table\n");
4656
4657     /* The names of the tables in the _Tables table must
4658        be in the same order as these names are created in
4659        the strings table. */
4660     query = "SELECT * FROM `_Tables`";
4661     r = MsiDatabaseOpenView(hdb, query, &hview);
4662     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4663     r = MsiViewExecute(hview, 0);
4664     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4665
4666     r = MsiViewFetch(hview, &hrec);
4667     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4668     sz = sizeof(buffer);
4669     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4671     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4672     r = MsiCloseHandle(hrec);
4673     ok(r == ERROR_SUCCESS, "failed to close record\n");
4674
4675     r = MsiViewFetch(hview, &hrec);
4676     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4677     sz = sizeof(buffer);
4678     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4680     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4681     r = MsiCloseHandle(hrec);
4682     ok(r == ERROR_SUCCESS, "failed to close record\n");
4683
4684     r = MsiViewFetch(hview, &hrec);
4685     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4686     sz = sizeof(buffer);
4687     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4689     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4690     r = MsiCloseHandle(hrec);
4691     ok(r == ERROR_SUCCESS, "failed to close record\n");
4692
4693     r = MsiViewClose(hview);
4694     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4695     r = MsiCloseHandle(hview);
4696     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4697
4698     /* The names of the tables in the _Columns table must
4699        be in the same order as these names are created in
4700        the strings table. */
4701     query = "SELECT * FROM `_Columns`";
4702     r = MsiDatabaseOpenView(hdb, query, &hview);
4703     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4704     r = MsiViewExecute(hview, 0);
4705     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4706
4707     r = MsiViewFetch(hview, &hrec);
4708     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4709     sz = sizeof(buffer);
4710     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4712     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4713     sz = sizeof(buffer);
4714     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4716     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4717     r = MsiCloseHandle(hrec);
4718     ok(r == ERROR_SUCCESS, "failed to close record\n");
4719
4720     r = MsiViewFetch(hview, &hrec);
4721     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4722     sz = sizeof(buffer);
4723     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4725     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4726     sz = sizeof(buffer);
4727     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4729     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4730     r = MsiCloseHandle(hrec);
4731     ok(r == ERROR_SUCCESS, "failed to close record\n");
4732
4733     r = MsiViewFetch(hview, &hrec);
4734     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4735     sz = sizeof(buffer);
4736     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4738     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4739     sz = sizeof(buffer);
4740     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4741     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4742     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4743     r = MsiCloseHandle(hrec);
4744     ok(r == ERROR_SUCCESS, "failed to close record\n");
4745
4746     r = MsiViewFetch(hview, &hrec);
4747     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4748     sz = sizeof(buffer);
4749     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4751     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4752     sz = sizeof(buffer);
4753     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4755     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4756     r = MsiCloseHandle(hrec);
4757     ok(r == ERROR_SUCCESS, "failed to close record\n");
4758
4759     r = MsiViewFetch(hview, &hrec);
4760     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4761     sz = sizeof(buffer);
4762     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4764     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4765     sz = sizeof(buffer);
4766     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4768     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4769     r = MsiCloseHandle(hrec);
4770     ok(r == ERROR_SUCCESS, "failed to close record\n");
4771
4772     r = MsiViewClose(hview);
4773     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4774     r = MsiCloseHandle(hview);
4775     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4776
4777     r = MsiCloseHandle(hdb);
4778     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4779
4780     DeleteFile(msifile);
4781 }
4782
4783 static void test_rows_order(void)
4784 {
4785     const char *query;
4786     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4787     UINT r;
4788     char buffer[100];
4789     DWORD sz;
4790
4791     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4792     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4793
4794     query = "CREATE TABLE `foo` ( "
4795         "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4796     r = run_query(hdb, 0, query);
4797     ok(r == ERROR_SUCCESS, "failed to create table\n");
4798
4799     r = run_query(hdb, 0, "INSERT INTO `foo` "
4800             "( `bar` ) VALUES ( 'A' )");
4801     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4802
4803     r = run_query(hdb, 0, "INSERT INTO `foo` "
4804             "( `bar` ) VALUES ( 'B' )");
4805     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4806
4807     r = run_query(hdb, 0, "INSERT INTO `foo` "
4808             "( `bar` ) VALUES ( 'C' )");
4809     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4810
4811     r = run_query(hdb, 0, "INSERT INTO `foo` "
4812             "( `bar` ) VALUES ( 'D' )");
4813     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4814
4815     r = run_query(hdb, 0, "INSERT INTO `foo` "
4816             "( `bar` ) VALUES ( 'E' )");
4817     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4818
4819     r = run_query(hdb, 0, "INSERT INTO `foo` "
4820             "( `bar` ) VALUES ( 'F' )");
4821     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4822
4823     query = "CREATE TABLE `bar` ( "
4824         "`foo` LONGCHAR NOT NULL, "
4825         "`baz` LONGCHAR NOT NULL "
4826         "PRIMARY KEY `foo` )";
4827     r = run_query(hdb, 0, query);
4828     ok(r == ERROR_SUCCESS, "failed to create table\n");
4829
4830     r = run_query(hdb, 0, "INSERT INTO `bar` "
4831             "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4832     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4833
4834     r = run_query(hdb, 0, "INSERT INTO `bar` "
4835             "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4836     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4837
4838     r = run_query(hdb, 0, "INSERT INTO `bar` "
4839             "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4840     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4841
4842     r = run_query(hdb, 0, "INSERT INTO `bar` "
4843             "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4844     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4845
4846     /* The rows of the table must be ordered by the column values of
4847        each row. For strings, the column value is the string id
4848        in the string table.  */
4849
4850     query = "SELECT * FROM `bar`";
4851     r = MsiDatabaseOpenView(hdb, query, &hview);
4852     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4853     r = MsiViewExecute(hview, 0);
4854     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4855
4856     r = MsiViewFetch(hview, &hrec);
4857     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4858     sz = sizeof(buffer);
4859     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4861     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4862     sz = sizeof(buffer);
4863     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4864     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4865     ok(!lstrcmp(buffer, "B"), "Expected B, got %s\n", buffer);
4866     r = MsiCloseHandle(hrec);
4867     ok(r == ERROR_SUCCESS, "failed to close record\n");
4868
4869     r = MsiViewFetch(hview, &hrec);
4870     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4871     sz = sizeof(buffer);
4872     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4874     ok(!lstrcmp(buffer, "C"), "Expected E, got %s\n", buffer);
4875     sz = sizeof(buffer);
4876     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4878     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4879     r = MsiCloseHandle(hrec);
4880     ok(r == ERROR_SUCCESS, "failed to close record\n");
4881
4882     r = MsiViewFetch(hview, &hrec);
4883     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4884     sz = sizeof(buffer);
4885     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4887     ok(!lstrcmp(buffer, "D"), "Expected D, got %s\n", buffer);
4888     sz = sizeof(buffer);
4889     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4890     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4891     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4892     r = MsiCloseHandle(hrec);
4893     ok(r == ERROR_SUCCESS, "failed to close record\n");
4894
4895     r = MsiViewFetch(hview, &hrec);
4896     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4897     sz = sizeof(buffer);
4898     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4900     ok(!lstrcmp(buffer, "F"), "Expected F, got %s\n", buffer);
4901     sz = sizeof(buffer);
4902     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4904     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4905     r = MsiCloseHandle(hrec);
4906     ok(r == ERROR_SUCCESS, "failed to close record\n");
4907
4908     r = MsiViewClose(hview);
4909     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4910     r = MsiCloseHandle(hview);
4911     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4912
4913     r = MsiCloseHandle(hdb);
4914     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4915
4916     DeleteFile(msifile);
4917 }
4918
4919 static void test_select_markers(void)
4920 {
4921     MSIHANDLE hdb = 0, rec, view, res;
4922     LPCSTR query;
4923     UINT r;
4924     DWORD size;
4925     CHAR buf[MAX_PATH];
4926
4927     hdb = create_db();
4928     ok( hdb, "failed to create db\n");
4929
4930     r = run_query(hdb, 0,
4931             "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
4932     ok(r == S_OK, "cannot create table: %d\n", r);
4933
4934     r = run_query(hdb, 0, "INSERT INTO `Table` "
4935             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
4936     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4937
4938     r = run_query(hdb, 0, "INSERT INTO `Table` "
4939             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
4940     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4941
4942     r = run_query(hdb, 0, "INSERT INTO `Table` "
4943             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
4944     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4945
4946     r = run_query(hdb, 0, "INSERT INTO `Table` "
4947             "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
4948     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4949
4950     rec = MsiCreateRecord(2);
4951     MsiRecordSetString(rec, 1, "apple");
4952     MsiRecordSetString(rec, 2, "two");
4953
4954     query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
4955     r = MsiDatabaseOpenView(hdb, query, &view);
4956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4957
4958     r = MsiViewExecute(view, rec);
4959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4960
4961     r = MsiViewFetch(view, &res);
4962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4963
4964     size = MAX_PATH;
4965     r = MsiRecordGetString(res, 1, buf, &size);
4966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4967     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
4968
4969     size = MAX_PATH;
4970     r = MsiRecordGetString(res, 2, buf, &size);
4971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4972     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
4973
4974     r = MsiRecordGetInteger(res, 3);
4975     ok(r == 1, "Expected 1, got %d\n", r);
4976
4977     MsiCloseHandle(res);
4978
4979     r = MsiViewFetch(view, &res);
4980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4981
4982     size = MAX_PATH;
4983     r = MsiRecordGetString(res, 1, buf, &size);
4984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4985     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
4986
4987     size = MAX_PATH;
4988     r = MsiRecordGetString(res, 2, buf, &size);
4989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4990     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
4991
4992     r = MsiRecordGetInteger(res, 3);
4993     ok(r == 2, "Expected 2, got %d\n", r);
4994
4995     MsiCloseHandle(res);
4996
4997     r = MsiViewFetch(view, &res);
4998     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4999
5000     MsiCloseHandle(rec);
5001     MsiViewClose(view);
5002     MsiCloseHandle(view);
5003
5004     rec = MsiCreateRecord(2);
5005     MsiRecordSetString(rec, 1, "one");
5006     MsiRecordSetInteger(rec, 2, 1);
5007
5008     query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5009     r = MsiDatabaseOpenView(hdb, query, &view);
5010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5011     r = MsiViewExecute(view, rec);
5012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5013
5014     r = MsiViewFetch(view, &res);
5015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5016
5017     size = MAX_PATH;
5018     r = MsiRecordGetString(res, 1, buf, &size);
5019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5020     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5021
5022     size = MAX_PATH;
5023     r = MsiRecordGetString(res, 2, buf, &size);
5024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5025     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5026
5027     r = MsiRecordGetInteger(res, 3);
5028     ok(r == 2, "Expected 2, got %d\n", r);
5029
5030     MsiCloseHandle(res);
5031
5032     r = MsiViewFetch(view, &res);
5033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5034
5035     size = MAX_PATH;
5036     r = MsiRecordGetString(res, 1, buf, &size);
5037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5038     ok(!lstrcmp(buf, "banana"), "Expected banana, got %s\n", buf);
5039
5040     size = MAX_PATH;
5041     r = MsiRecordGetString(res, 2, buf, &size);
5042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5043     ok(!lstrcmp(buf, "three"), "Expected three, got %s\n", buf);
5044
5045     r = MsiRecordGetInteger(res, 3);
5046     ok(r == 3, "Expected 3, got %d\n", r);
5047
5048     MsiCloseHandle(res);
5049
5050     r = MsiViewFetch(view, &res);
5051     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5052
5053     MsiCloseHandle(rec);
5054     MsiViewClose(view);
5055     MsiCloseHandle(view);
5056     MsiCloseHandle(hdb);
5057     DeleteFile(msifile);
5058 }
5059
5060 static void test_viewmodify_update(void)
5061 {
5062     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5063     const char *query;
5064     UINT r;
5065
5066     DeleteFile(msifile);
5067
5068     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5069     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5070
5071     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5072     r = run_query( hdb, 0, query );
5073     ok(r == ERROR_SUCCESS, "query failed\n");
5074
5075     query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5076     r = run_query( hdb, 0, query );
5077     ok(r == ERROR_SUCCESS, "query failed\n");
5078
5079     query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5080     r = run_query( hdb, 0, query );
5081     ok(r == ERROR_SUCCESS, "query failed\n");
5082
5083     query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5084     r = run_query( hdb, 0, query );
5085     ok(r == ERROR_SUCCESS, "query failed\n");
5086
5087     query = "SELECT `B` FROM `table`";
5088     r = MsiDatabaseOpenView(hdb, query, &hview);
5089     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5090     r = MsiViewExecute(hview, 0);
5091     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5092     r = MsiViewFetch(hview, &hrec);
5093     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5094
5095     r = MsiRecordSetInteger(hrec, 1, 0);
5096     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5097
5098     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5099     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5100
5101     r = MsiCloseHandle(hrec);
5102     ok(r == ERROR_SUCCESS, "failed to close record\n");
5103
5104     r = MsiViewClose(hview);
5105     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5106     r = MsiCloseHandle(hview);
5107     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5108
5109     query = "SELECT * FROM `table`";
5110     r = MsiDatabaseOpenView(hdb, query, &hview);
5111     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5112     r = MsiViewExecute(hview, 0);
5113     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5114     r = MsiViewFetch(hview, &hrec);
5115     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5116
5117     r = MsiRecordGetInteger(hrec, 1);
5118     ok(r == 1, "Expected 1, got %d\n", r);
5119     r = MsiRecordGetInteger(hrec, 2);
5120     ok(r == 0, "Expected 0, got %d\n", r);
5121
5122     r = MsiCloseHandle(hrec);
5123     ok(r == ERROR_SUCCESS, "failed to close record\n");
5124
5125     r = MsiViewFetch(hview, &hrec);
5126     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5127
5128     r = MsiRecordGetInteger(hrec, 1);
5129     ok(r == 3, "Expected 3, got %d\n", r);
5130     r = MsiRecordGetInteger(hrec, 2);
5131     ok(r == 4, "Expected 4, got %d\n", r);
5132
5133     r = MsiCloseHandle(hrec);
5134     ok(r == ERROR_SUCCESS, "failed to close record\n");
5135
5136     r = MsiViewFetch(hview, &hrec);
5137     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5138
5139     r = MsiRecordGetInteger(hrec, 1);
5140     ok(r == 5, "Expected 5, got %d\n", r);
5141     r = MsiRecordGetInteger(hrec, 2);
5142     ok(r == 6, "Expected 6, got %d\n", r);
5143
5144     r = MsiCloseHandle(hrec);
5145     ok(r == ERROR_SUCCESS, "failed to close record\n");
5146
5147     r = MsiViewFetch(hview, &hrec);
5148     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5149
5150     r = MsiViewClose(hview);
5151     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5152     r = MsiCloseHandle(hview);
5153     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5154
5155     /* loop through all elements */
5156     query = "SELECT `B` FROM `table`";
5157     r = MsiDatabaseOpenView(hdb, query, &hview);
5158     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5159     r = MsiViewExecute(hview, 0);
5160     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5161
5162     while (TRUE)
5163     {
5164         r = MsiViewFetch(hview, &hrec);
5165         if (r != ERROR_SUCCESS)
5166             break;
5167
5168         r = MsiRecordSetInteger(hrec, 1, 0);
5169         ok(r == ERROR_SUCCESS, "failed to set integer\n");
5170
5171         r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5172         ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5173
5174         r = MsiCloseHandle(hrec);
5175         ok(r == ERROR_SUCCESS, "failed to close record\n");
5176     }
5177
5178     r = MsiViewClose(hview);
5179     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5180     r = MsiCloseHandle(hview);
5181     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5182
5183     query = "SELECT * FROM `table`";
5184     r = MsiDatabaseOpenView(hdb, query, &hview);
5185     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5186     r = MsiViewExecute(hview, 0);
5187     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5188     r = MsiViewFetch(hview, &hrec);
5189     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5190
5191     r = MsiRecordGetInteger(hrec, 1);
5192     ok(r == 1, "Expected 1, got %d\n", r);
5193     r = MsiRecordGetInteger(hrec, 2);
5194     ok(r == 0, "Expected 0, got %d\n", r);
5195
5196     r = MsiCloseHandle(hrec);
5197     ok(r == ERROR_SUCCESS, "failed to close record\n");
5198
5199     r = MsiViewFetch(hview, &hrec);
5200     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5201
5202     r = MsiRecordGetInteger(hrec, 1);
5203     ok(r == 3, "Expected 3, got %d\n", r);
5204     r = MsiRecordGetInteger(hrec, 2);
5205     ok(r == 0, "Expected 0, got %d\n", r);
5206
5207     r = MsiCloseHandle(hrec);
5208     ok(r == ERROR_SUCCESS, "failed to close record\n");
5209
5210     r = MsiViewFetch(hview, &hrec);
5211     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5212
5213     r = MsiRecordGetInteger(hrec, 1);
5214     ok(r == 5, "Expected 5, got %d\n", r);
5215     r = MsiRecordGetInteger(hrec, 2);
5216     ok(r == 0, "Expected 0, got %d\n", r);
5217
5218     r = MsiCloseHandle(hrec);
5219     ok(r == ERROR_SUCCESS, "failed to close record\n");
5220
5221     r = MsiViewFetch(hview, &hrec);
5222     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5223
5224     r = MsiViewClose(hview);
5225     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5226     r = MsiCloseHandle(hview);
5227     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5228
5229     r = MsiCloseHandle( hdb );
5230     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5231 }
5232
5233 static void test_viewmodify_assign(void)
5234 {
5235     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5236     const char *query;
5237     UINT r;
5238
5239     /* setup database */
5240     DeleteFile(msifile);
5241
5242     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5243     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5244
5245     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5246     r = run_query( hdb, 0, query );
5247     ok(r == ERROR_SUCCESS, "query failed\n");
5248
5249     /* assign to view, new primary key */
5250     query = "SELECT * FROM `table`";
5251     r = MsiDatabaseOpenView(hdb, query, &hview);
5252     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5253     r = MsiViewExecute(hview, 0);
5254     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5255
5256     hrec = MsiCreateRecord(2);
5257     ok(hrec != 0, "MsiCreateRecord failed\n");
5258
5259     r = MsiRecordSetInteger(hrec, 1, 1);
5260     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5261     r = MsiRecordSetInteger(hrec, 2, 2);
5262     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5263
5264     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5265     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5266
5267     r = MsiCloseHandle(hrec);
5268     ok(r == ERROR_SUCCESS, "failed to close record\n");
5269
5270     r = MsiViewClose(hview);
5271     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5272     r = MsiCloseHandle(hview);
5273     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5274
5275     query = "SELECT * FROM `table`";
5276     r = MsiDatabaseOpenView(hdb, query, &hview);
5277     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5278     r = MsiViewExecute(hview, 0);
5279     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5280     r = MsiViewFetch(hview, &hrec);
5281     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5282
5283     r = MsiRecordGetInteger(hrec, 1);
5284     ok(r == 1, "Expected 1, got %d\n", r);
5285     r = MsiRecordGetInteger(hrec, 2);
5286     ok(r == 2, "Expected 2, got %d\n", r);
5287
5288     r = MsiCloseHandle(hrec);
5289     ok(r == ERROR_SUCCESS, "failed to close record\n");
5290
5291     r = MsiViewFetch(hview, &hrec);
5292     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5293
5294     r = MsiViewClose(hview);
5295     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5296     r = MsiCloseHandle(hview);
5297     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5298
5299     /* assign to view, primary key matches */
5300     query = "SELECT * FROM `table`";
5301     r = MsiDatabaseOpenView(hdb, query, &hview);
5302     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5303     r = MsiViewExecute(hview, 0);
5304     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5305
5306     hrec = MsiCreateRecord(2);
5307     ok(hrec != 0, "MsiCreateRecord failed\n");
5308
5309     r = MsiRecordSetInteger(hrec, 1, 1);
5310     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5311     r = MsiRecordSetInteger(hrec, 2, 4);
5312     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5313
5314     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5315     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5316
5317     r = MsiCloseHandle(hrec);
5318     ok(r == ERROR_SUCCESS, "failed to close record\n");
5319
5320     r = MsiViewClose(hview);
5321     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5322     r = MsiCloseHandle(hview);
5323     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5324
5325     query = "SELECT * FROM `table`";
5326     r = MsiDatabaseOpenView(hdb, query, &hview);
5327     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5328     r = MsiViewExecute(hview, 0);
5329     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5330     r = MsiViewFetch(hview, &hrec);
5331     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5332
5333     r = MsiRecordGetInteger(hrec, 1);
5334     ok(r == 1, "Expected 1, got %d\n", r);
5335     r = MsiRecordGetInteger(hrec, 2);
5336     ok(r == 4, "Expected 4, got %d\n", r);
5337
5338     r = MsiCloseHandle(hrec);
5339     ok(r == ERROR_SUCCESS, "failed to close record\n");
5340
5341     r = MsiViewFetch(hview, &hrec);
5342     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5343
5344     r = MsiViewClose(hview);
5345     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5346     r = MsiCloseHandle(hview);
5347     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5348
5349     /* close database */
5350     r = MsiCloseHandle( hdb );
5351     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5352 }
5353
5354 static const WCHAR data10[] = { /* MOO */
5355     0x8001, 0x000b,
5356 };
5357 static const WCHAR data11[] = { /* AAR */
5358     0x8002, 0x8005,
5359     0x000c, 0x000f,
5360 };
5361 static const char data12[] = /* _StringData */
5362     "MOOABAARCDonetwofourfive";
5363 static const WCHAR data13[] = { /* _StringPool */
5364 /*  len, refs */
5365     0,   0,    /* string 0 ''     */
5366     0,   0,    /* string 1 ''     */
5367     0,   0,    /* string 2 ''     */
5368     0,   0,    /* string 3 ''     */
5369     0,   0,    /* string 4 ''     */
5370     3,   3,    /* string 5 'MOO'  */
5371     1,   1,    /* string 6 'A'    */
5372     1,   1,    /* string 7 'B'    */
5373     3,   3,    /* string 8 'AAR'  */
5374     1,   1,    /* string 9 'C'    */
5375     1,   1,    /* string a 'D'    */
5376     3,   1,    /* string b 'one'  */
5377     3,   1,    /* string c 'two'  */
5378     0,   0,    /* string d ''     */
5379     4,   1,    /* string e 'four' */
5380     4,   1,    /* string f 'five' */
5381 };
5382
5383 static void test_stringtable(void)
5384 {
5385     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5386     IStorage *stg = NULL;
5387     IStream *stm;
5388     WCHAR name[0x20];
5389     HRESULT hr;
5390     const char *query;
5391     char buffer[MAX_PATH];
5392     WCHAR data[MAX_PATH];
5393     DWORD sz, read;
5394     UINT r;
5395
5396     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5397     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5398     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5399     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5400     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5401
5402     DeleteFile(msifile);
5403
5404     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5406
5407     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5408     r = run_query(hdb, 0, query);
5409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5410
5411     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5412     r = run_query(hdb, 0, query);
5413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5414
5415     /* insert persistent row */
5416     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5417     r = run_query(hdb, 0, query);
5418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5419
5420     /* insert persistent row */
5421     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5422     r = run_query(hdb, 0, query);
5423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5424
5425     /* open a view */
5426     query = "SELECT * FROM `MOO`";
5427     r = MsiDatabaseOpenView(hdb, query, &hview);
5428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5429     r = MsiViewExecute(hview, 0);
5430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5431
5432     hrec = MsiCreateRecord(2);
5433
5434     r = MsiRecordSetInteger(hrec, 1, 3);
5435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5436     r = MsiRecordSetString(hrec, 2, "three");
5437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5438
5439     /* insert a nonpersistent row */
5440     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5442
5443     r = MsiCloseHandle(hrec);
5444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5445     r = MsiViewClose(hview);
5446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5447     r = MsiCloseHandle(hview);
5448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5449
5450     /* insert persistent row */
5451     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5452     r = run_query(hdb, 0, query);
5453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5454
5455     /* insert persistent row */
5456     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5457     r = run_query(hdb, 0, query);
5458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5459
5460     r = MsiDatabaseCommit(hdb);
5461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5462
5463     r = MsiCloseHandle(hdb);
5464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5465
5466     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
5467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5468
5469     query = "SELECT * FROM `MOO`";
5470     r = MsiDatabaseOpenView(hdb, query, &hview);
5471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5472
5473     r = MsiViewExecute(hview, 0);
5474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5475
5476     r = MsiViewFetch(hview, &hrec);
5477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5478
5479     r = MsiRecordGetFieldCount(hrec);
5480     ok(r == 2, "Expected 2, got %d\n", r);
5481
5482     r = MsiRecordGetInteger(hrec, 1);
5483     ok(r == 1, "Expected 1, got %d\n", r);
5484
5485     sz = sizeof(buffer);
5486     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5487     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5488     ok(!lstrcmp(buffer, "one"), "Expected one, got %s\n", buffer);
5489
5490     r = MsiCloseHandle(hrec);
5491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5492
5493     r = MsiViewFetch(hview, &hrec);
5494     todo_wine
5495     {
5496         ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5497     }
5498
5499     r = MsiViewClose(hview);
5500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5501     r = MsiCloseHandle(hview);
5502     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5503     r = MsiCloseHandle(hrec);
5504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5505
5506     query = "SELECT * FROM `AAR`";
5507     r = MsiDatabaseOpenView(hdb, query, &hview);
5508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5509
5510     r = MsiViewExecute(hview, 0);
5511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5512
5513     r = MsiViewFetch(hview, &hrec);
5514     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5515
5516     r = MsiRecordGetFieldCount(hrec);
5517     ok(r == 2, "Expected 2, got %d\n", r);
5518
5519     r = MsiRecordGetInteger(hrec, 1);
5520     ok(r == 2, "Expected 2, got %d\n", r);
5521
5522     sz = sizeof(buffer);
5523     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5525     ok(!lstrcmp(buffer, "two"), "Expected two, got %s\n", buffer);
5526
5527     r = MsiCloseHandle(hrec);
5528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5529
5530     r = MsiViewFetch(hview, &hrec);
5531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5532
5533     r = MsiRecordGetFieldCount(hrec);
5534     ok(r == 2, "Expected 2, got %d\n", r);
5535
5536     r = MsiRecordGetInteger(hrec, 1);
5537     ok(r == 5, "Expected 5, got %d\n", r);
5538
5539     sz = sizeof(buffer);
5540     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5542     ok(!lstrcmp(buffer, "five"), "Expected five, got %s\n", buffer);
5543
5544     r = MsiCloseHandle(hrec);
5545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5546
5547     r = MsiViewFetch(hview, &hrec);
5548     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5549
5550     r = MsiViewClose(hview);
5551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5552     r = MsiCloseHandle(hview);
5553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5554     r = MsiCloseHandle(hrec);
5555     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5556     r = MsiCloseHandle(hdb);
5557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5558
5559     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5560     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5561     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5562     ok(stg != NULL, "Expected non-NULL storage\n");
5563
5564     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5565     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5566     ok(stm != NULL, "Expected non-NULL stream\n");
5567
5568     hr = IStream_Read(stm, data, MAX_PATH, &read);
5569     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5570     todo_wine
5571     {
5572         ok(read == 4, "Expected 4, got %d\n", read);
5573         ok(!memcmp(data, data10, read), "Unexpected data\n");
5574     }
5575
5576     hr = IStream_Release(stm);
5577     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5578
5579     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5580     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5581     ok(stm != NULL, "Expected non-NULL stream\n");
5582
5583     hr = IStream_Read(stm, data, MAX_PATH, &read);
5584     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5585     ok(read == 8, "Expected 8, got %d\n", read);
5586     todo_wine
5587     {
5588         ok(!memcmp(data, data11, read), "Unexpected data\n");
5589     }
5590
5591     hr = IStream_Release(stm);
5592     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5593
5594     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5595     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5596     ok(stm != NULL, "Expected non-NULL stream\n");
5597
5598     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5599     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5600     ok(read == 24, "Expected 24, got %d\n", read);
5601     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5602
5603     hr = IStream_Release(stm);
5604     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5605
5606     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5607     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5608     ok(stm != NULL, "Expected non-NULL stream\n");
5609
5610     hr = IStream_Read(stm, data, MAX_PATH, &read);
5611     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5612     todo_wine
5613     {
5614         ok(read == 64, "Expected 64, got %d\n", read);
5615         ok(!memcmp(data, data13, read), "Unexpected data\n");
5616     }
5617
5618     hr = IStream_Release(stm);
5619     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5620
5621     hr = IStorage_Release(stg);
5622     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5623
5624     DeleteFileA(msifile);
5625 }
5626
5627 static void test_viewmodify_delete(void)
5628 {
5629     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5630     UINT r;
5631     const char *query;
5632     char buffer[0x100];
5633     DWORD sz;
5634
5635     DeleteFile(msifile);
5636
5637     /* just MsiOpenDatabase should not create a file */
5638     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5640
5641     query = "CREATE TABLE `phone` ( "
5642             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
5643             "PRIMARY KEY `id`)";
5644     r = run_query(hdb, 0, query);
5645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5646
5647     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5648         "VALUES('1', 'Alan', '5030581')";
5649     r = run_query(hdb, 0, query);
5650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5651
5652     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5653         "VALUES('2', 'Barry', '928440')";
5654     r = run_query(hdb, 0, query);
5655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5656
5657     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5658         "VALUES('3', 'Cindy', '2937550')";
5659     r = run_query(hdb, 0, query);
5660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5661
5662     query = "SELECT * FROM `phone` WHERE `id` <= 2";
5663     r = MsiDatabaseOpenView(hdb, query, &hview);
5664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5665     r = MsiViewExecute(hview, 0);
5666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5667     r = MsiViewFetch(hview, &hrec);
5668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5669
5670     /* delete 1 */
5671     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5673
5674     r = MsiCloseHandle(hrec);
5675     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5676     r = MsiViewFetch(hview, &hrec);
5677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5678
5679     /* delete 2 */
5680     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5682
5683     r = MsiCloseHandle(hrec);
5684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5685     r = MsiViewClose(hview);
5686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5687     r = MsiCloseHandle(hview);
5688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5689
5690     query = "SELECT * FROM `phone`";
5691     r = MsiDatabaseOpenView(hdb, query, &hview);
5692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5693     r = MsiViewExecute(hview, 0);
5694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5695     r = MsiViewFetch(hview, &hrec);
5696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5697
5698     r = MsiRecordGetInteger(hrec, 1);
5699     ok(r == 3, "Expected 3, got %d\n", r);
5700
5701     sz = sizeof(buffer);
5702     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5704     ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
5705
5706     sz = sizeof(buffer);
5707     r = MsiRecordGetString(hrec, 3, buffer, &sz);
5708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5709     ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
5710
5711     r = MsiCloseHandle(hrec);
5712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5713
5714     r = MsiViewFetch(hview, &hrec);
5715     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5716
5717     r = MsiViewClose(hview);
5718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5719     r = MsiCloseHandle(hview);
5720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5721     r = MsiCloseHandle(hdb);
5722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5723 }
5724
5725 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
5726 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
5727 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
5728
5729 static const WCHAR data14[] = { /* _StringPool */
5730 /*  len, refs */
5731     0,   0,    /* string 0 ''    */
5732 };
5733
5734 static const struct {
5735     LPCWSTR name;
5736     const void *data;
5737     DWORD size;
5738 } database_table_data[] =
5739 {
5740     {_Tables, NULL, 0},
5741     {_StringData, NULL, 0},
5742     {_StringPool, data14, sizeof data14},
5743 };
5744
5745 static void enum_stream_names(IStorage *stg)
5746 {
5747     IEnumSTATSTG *stgenum = NULL;
5748     IStream *stm;
5749     HRESULT hr;
5750     STATSTG stat;
5751     ULONG n, count;
5752     BYTE data[MAX_PATH];
5753     BYTE check[MAX_PATH];
5754     DWORD sz;
5755
5756     memset(check, 'a', MAX_PATH);
5757
5758     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
5759     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5760
5761     n = 0;
5762     while(TRUE)
5763     {
5764         count = 0;
5765         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
5766         if(FAILED(hr) || !count)
5767             break;
5768
5769         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
5770            "Expected table %d name to match\n", n);
5771
5772         stm = NULL;
5773         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
5774                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5775         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5776         ok(stm != NULL, "Expected non-NULL stream\n");
5777
5778         CoTaskMemFree(stat.pwcsName);
5779
5780         sz = MAX_PATH;
5781         memset(data, 'a', MAX_PATH);
5782         hr = IStream_Read(stm, data, sz, &count);
5783         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5784
5785         ok(count == database_table_data[n].size,
5786            "Expected %d, got %d\n", database_table_data[n].size, count);
5787
5788         if (!database_table_data[n].size)
5789             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
5790         else
5791             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
5792                "Expected table %d data to match\n", n);
5793
5794         IStream_Release(stm);
5795         n++;
5796     }
5797
5798     ok(n == 3, "Expected 3, got %d\n", n);
5799
5800     IEnumSTATSTG_Release(stgenum);
5801 }
5802
5803 static void test_defaultdatabase(void)
5804 {
5805     UINT r;
5806     HRESULT hr;
5807     MSIHANDLE hdb;
5808     IStorage *stg = NULL;
5809
5810     DeleteFile(msifile);
5811
5812     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5814
5815     r = MsiDatabaseCommit(hdb);
5816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5817
5818     MsiCloseHandle(hdb);
5819
5820     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
5821     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5822     ok(stg != NULL, "Expected non-NULL stg\n");
5823
5824     enum_stream_names(stg);
5825
5826     IStorage_Release(stg);
5827     DeleteFileA(msifile);
5828 }
5829
5830 static void test_order(void)
5831 {
5832     MSIHANDLE hdb, hview, hrec;
5833     CHAR buffer[MAX_PATH];
5834     LPCSTR query;
5835     UINT r, sz;
5836     int val;
5837
5838     hdb = create_db();
5839     ok(hdb, "failed to create db\n");
5840
5841     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
5842     r = run_query(hdb, 0, query);
5843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5844
5845     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
5846     r = run_query(hdb, 0, query);
5847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5848
5849     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
5850     r = run_query(hdb, 0, query);
5851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5852
5853     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
5854     r = run_query(hdb, 0, query);
5855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5856
5857     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
5858     r = run_query(hdb, 0, query);
5859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5860
5861     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
5862     r = run_query(hdb, 0, query);
5863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5864
5865     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
5866     r = run_query(hdb, 0, query);
5867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5868
5869     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
5870     r = run_query(hdb, 0, query);
5871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5872
5873     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
5874     r = run_query(hdb, 0, query);
5875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5876
5877     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
5878     r = MsiDatabaseOpenView(hdb, query, &hview);
5879     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5880     r = MsiViewExecute(hview, 0);
5881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5882
5883     r = MsiViewFetch(hview, &hrec);
5884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5885
5886     val = MsiRecordGetInteger(hrec, 1);
5887     ok(val == 3, "Expected 3, got %d\n", val);
5888
5889     val = MsiRecordGetInteger(hrec, 2);
5890     ok(val == 4, "Expected 3, got %d\n", val);
5891
5892     MsiCloseHandle(hrec);
5893
5894     r = MsiViewFetch(hview, &hrec);
5895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5896
5897     val = MsiRecordGetInteger(hrec, 1);
5898     ok(val == 5, "Expected 5, got %d\n", val);
5899
5900     val = MsiRecordGetInteger(hrec, 2);
5901     ok(val == 6, "Expected 6, got %d\n", val);
5902
5903     MsiCloseHandle(hrec);
5904
5905     r = MsiViewFetch(hview, &hrec);
5906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5907
5908     val = MsiRecordGetInteger(hrec, 1);
5909     ok(val == 1, "Expected 1, got %d\n", val);
5910
5911     val = MsiRecordGetInteger(hrec, 2);
5912     ok(val == 2, "Expected 2, got %d\n", val);
5913
5914     MsiCloseHandle(hrec);
5915
5916     r = MsiViewFetch(hview, &hrec);
5917     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5918
5919     MsiViewClose(hview);
5920     MsiCloseHandle(hview);
5921
5922     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
5923     r = MsiDatabaseOpenView(hdb, query, &hview);
5924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5925     r = MsiViewExecute(hview, 0);
5926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5927
5928     r = MsiViewFetch(hview, &hrec);
5929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5930
5931     val = MsiRecordGetInteger(hrec, 1);
5932     ok(val == 1, "Expected 1, got %d\n", val);
5933
5934     val = MsiRecordGetInteger(hrec, 2);
5935     ok(val == 12, "Expected 12, got %d\n", val);
5936
5937     MsiCloseHandle(hrec);
5938
5939     r = MsiViewFetch(hview, &hrec);
5940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5941
5942     val = MsiRecordGetInteger(hrec, 1);
5943     ok(val == 3, "Expected 3, got %d\n", val);
5944
5945     val = MsiRecordGetInteger(hrec, 2);
5946     ok(val == 12, "Expected 12, got %d\n", val);
5947
5948     MsiCloseHandle(hrec);
5949
5950     r = MsiViewFetch(hview, &hrec);
5951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5952
5953     val = MsiRecordGetInteger(hrec, 1);
5954     ok(val == 5, "Expected 5, got %d\n", val);
5955
5956     val = MsiRecordGetInteger(hrec, 2);
5957     ok(val == 12, "Expected 12, got %d\n", val);
5958
5959     MsiCloseHandle(hrec);
5960
5961     r = MsiViewFetch(hview, &hrec);
5962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5963
5964     val = MsiRecordGetInteger(hrec, 1);
5965     ok(val == 1, "Expected 1, got %d\n", val);
5966
5967     val = MsiRecordGetInteger(hrec, 2);
5968     ok(val == 14, "Expected 14, got %d\n", val);
5969
5970     MsiCloseHandle(hrec);
5971
5972     r = MsiViewFetch(hview, &hrec);
5973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5974
5975     val = MsiRecordGetInteger(hrec, 1);
5976     ok(val == 3, "Expected 3, got %d\n", val);
5977
5978     val = MsiRecordGetInteger(hrec, 2);
5979     ok(val == 14, "Expected 14, got %d\n", val);
5980
5981     MsiCloseHandle(hrec);
5982
5983     r = MsiViewFetch(hview, &hrec);
5984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5985
5986     val = MsiRecordGetInteger(hrec, 1);
5987     ok(val == 5, "Expected 5, got %d\n", val);
5988
5989     val = MsiRecordGetInteger(hrec, 2);
5990     ok(val == 14, "Expected 14, got %d\n", val);
5991
5992     MsiCloseHandle(hrec);
5993
5994     r = MsiViewFetch(hview, &hrec);
5995     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5996
5997     val = MsiRecordGetInteger(hrec, 1);
5998     ok(val == 1, "Expected 1, got %d\n", val);
5999
6000     val = MsiRecordGetInteger(hrec, 2);
6001     ok(val == 10, "Expected 10, got %d\n", val);
6002
6003     MsiCloseHandle(hrec);
6004
6005     r = MsiViewFetch(hview, &hrec);
6006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6007
6008     val = MsiRecordGetInteger(hrec, 1);
6009     ok(val == 3, "Expected 3, got %d\n", val);
6010
6011     val = MsiRecordGetInteger(hrec, 2);
6012     ok(val == 10, "Expected 10, got %d\n", val);
6013
6014     MsiCloseHandle(hrec);
6015
6016     r = MsiViewFetch(hview, &hrec);
6017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6018
6019     val = MsiRecordGetInteger(hrec, 1);
6020     ok(val == 5, "Expected 5, got %d\n", val);
6021
6022     val = MsiRecordGetInteger(hrec, 2);
6023     ok(val == 10, "Expected 10, got %d\n", val);
6024
6025     MsiCloseHandle(hrec);
6026
6027     r = MsiViewFetch(hview, &hrec);
6028     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6029
6030     MsiViewClose(hview);
6031     MsiCloseHandle(hview);
6032
6033     query = "SELECT * FROM `Empty` ORDER BY `A`";
6034     r = MsiDatabaseOpenView(hdb, query, &hview);
6035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6036     r = MsiViewExecute(hview, 0);
6037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6038
6039     r = MsiViewFetch(hview, &hrec);
6040     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6041
6042     MsiViewClose(hview);
6043     MsiCloseHandle(hview);
6044
6045     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6046     r = run_query(hdb, 0, query);
6047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6048
6049     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6050     r = run_query(hdb, 0, query);
6051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6052
6053     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6054     r = run_query(hdb, 0, query);
6055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6056
6057     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6058     r = run_query(hdb, 0, query);
6059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6060
6061     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6062     r = MsiDatabaseOpenView(hdb, query, &hview);
6063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6064     r = MsiViewExecute(hview, 0);
6065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6066
6067     r = MsiViewFetch(hview, &hrec);
6068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6069
6070     sz = sizeof(buffer);
6071     r = MsiRecordGetString(hrec, 1, buffer, &sz);
6072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6073     ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6074
6075     r = MsiRecordGetInteger(hrec, 2);
6076     ok(r == 3, "Expected 3, got %d\n", r);
6077
6078     MsiCloseHandle(hrec);
6079
6080     r = MsiViewFetch(hview, &hrec);
6081     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6082
6083     MsiViewClose(hview);
6084     MsiCloseHandle(hview);
6085     MsiCloseHandle(hdb);
6086 }
6087
6088 static void test_viewmodify_delete_temporary(void)
6089 {
6090     MSIHANDLE hdb, hview, hrec;
6091     const char *query;
6092     UINT r;
6093
6094     DeleteFile(msifile);
6095
6096     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6098
6099     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6100     r = run_query(hdb, 0, query);
6101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6102
6103     query = "SELECT * FROM `Table`";
6104     r = MsiDatabaseOpenView(hdb, query, &hview);
6105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6106     r = MsiViewExecute(hview, 0);
6107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6108
6109     hrec = MsiCreateRecord(1);
6110     MsiRecordSetInteger(hrec, 1, 1);
6111
6112     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6113     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6114
6115     MsiCloseHandle(hrec);
6116
6117     hrec = MsiCreateRecord(1);
6118     MsiRecordSetInteger(hrec, 1, 2);
6119
6120     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6121     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6122
6123     MsiCloseHandle(hrec);
6124
6125     hrec = MsiCreateRecord(1);
6126     MsiRecordSetInteger(hrec, 1, 3);
6127
6128     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6130
6131     MsiCloseHandle(hrec);
6132
6133     hrec = MsiCreateRecord(1);
6134     MsiRecordSetInteger(hrec, 1, 4);
6135
6136     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6138
6139     MsiCloseHandle(hrec);
6140     MsiViewClose(hview);
6141     MsiCloseHandle(hview);
6142
6143     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6144     r = MsiDatabaseOpenView(hdb, query, &hview);
6145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6146     r = MsiViewExecute(hview, 0);
6147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6148     r = MsiViewFetch(hview, &hrec);
6149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6150
6151     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6153
6154     MsiCloseHandle(hrec);
6155     MsiViewClose(hview);
6156     MsiCloseHandle(hview);
6157
6158     query = "SELECT * FROM `Table` WHERE  `A` = 3";
6159     r = MsiDatabaseOpenView(hdb, query, &hview);
6160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6161     r = MsiViewExecute(hview, 0);
6162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6163     r = MsiViewFetch(hview, &hrec);
6164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6165
6166     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6168
6169     MsiCloseHandle(hrec);
6170     MsiViewClose(hview);
6171     MsiCloseHandle(hview);
6172
6173     query = "SELECT * FROM `Table` ORDER BY `A`";
6174     r = MsiDatabaseOpenView(hdb, query, &hview);
6175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6176     r = MsiViewExecute(hview, 0);
6177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6178
6179     r = MsiViewFetch(hview, &hrec);
6180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6181
6182     r = MsiRecordGetInteger(hrec, 1);
6183     ok(r == 1, "Expected 1, got %d\n", r);
6184
6185     MsiCloseHandle(hrec);
6186
6187     r = MsiViewFetch(hview, &hrec);
6188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6189
6190     r = MsiRecordGetInteger(hrec, 1);
6191     ok(r == 4, "Expected 4, got %d\n", r);
6192
6193     MsiCloseHandle(hrec);
6194
6195     r = MsiViewFetch(hview, &hrec);
6196     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6197
6198     MsiViewClose(hview);
6199     MsiCloseHandle(hview);
6200     MsiCloseHandle(hdb);
6201     DeleteFileA(msifile);
6202 }
6203
6204 static void test_deleterow(void)
6205 {
6206     MSIHANDLE hdb, hview, hrec;
6207     const char *query;
6208     char buf[MAX_PATH];
6209     UINT r;
6210     DWORD size;
6211
6212     DeleteFile(msifile);
6213
6214     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6216
6217     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6218     r = run_query(hdb, 0, query);
6219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6220
6221     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6222     r = run_query(hdb, 0, query);
6223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6224
6225     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6226     r = run_query(hdb, 0, query);
6227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6228
6229     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6230     r = run_query(hdb, 0, query);
6231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6232
6233     r = MsiDatabaseCommit(hdb);
6234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6235
6236     MsiCloseHandle(hdb);
6237
6238     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
6239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6240
6241     query = "SELECT * FROM `Table`";
6242     r = MsiDatabaseOpenView(hdb, query, &hview);
6243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6244     r = MsiViewExecute(hview, 0);
6245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6246
6247     r = MsiViewFetch(hview, &hrec);
6248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6249
6250     size = MAX_PATH;
6251     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6253     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6254
6255     MsiCloseHandle(hrec);
6256
6257     r = MsiViewFetch(hview, &hrec);
6258     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6259
6260     MsiViewClose(hview);
6261     MsiCloseHandle(hview);
6262     MsiCloseHandle(hdb);
6263     DeleteFileA(msifile);
6264 }
6265
6266 static const CHAR import_dat[] = "A\n"
6267                                  "s72\n"
6268                                  "Table\tA\n"
6269                                  "This is a new 'string' ok\n";
6270
6271 static void test_quotes(void)
6272 {
6273     MSIHANDLE hdb, hview, hrec;
6274     const char *query;
6275     char buf[MAX_PATH];
6276     UINT r;
6277     DWORD size;
6278
6279     DeleteFile(msifile);
6280
6281     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6283
6284     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6285     r = run_query(hdb, 0, query);
6286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6287
6288     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6289     r = run_query(hdb, 0, query);
6290     ok(r == ERROR_BAD_QUERY_SYNTAX,
6291        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6292
6293     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6294     r = run_query(hdb, 0, query);
6295     ok(r == ERROR_BAD_QUERY_SYNTAX,
6296        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6297
6298     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6299     r = run_query(hdb, 0, query);
6300     ok(r == ERROR_BAD_QUERY_SYNTAX,
6301        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6302
6303     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6304     r = run_query(hdb, 0, query);
6305     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6306
6307     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6308     r = run_query(hdb, 0, query);
6309     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6310
6311     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6312     r = run_query(hdb, 0, query);
6313     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6314
6315     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6316     r = run_query(hdb, 0, query);
6317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6318
6319     query = "SELECT * FROM `Table`";
6320     r = MsiDatabaseOpenView(hdb, query, &hview);
6321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6322
6323     r = MsiViewExecute(hview, 0);
6324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6325
6326     r = MsiViewFetch(hview, &hrec);
6327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6328
6329     size = MAX_PATH;
6330     r = MsiRecordGetString(hrec, 1, buf, &size);
6331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6332     ok(!lstrcmp(buf, "This is a \"string\" ok"),
6333        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6334
6335     MsiCloseHandle(hrec);
6336
6337     r = MsiViewFetch(hview, &hrec);
6338     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6339
6340     MsiViewClose(hview);
6341     MsiCloseHandle(hview);
6342
6343     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6344
6345     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6347
6348     DeleteFileA("import.idt");
6349
6350     query = "SELECT * FROM `Table`";
6351     r = MsiDatabaseOpenView(hdb, query, &hview);
6352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6353
6354     r = MsiViewExecute(hview, 0);
6355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6356
6357     r = MsiViewFetch(hview, &hrec);
6358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6359
6360     size = MAX_PATH;
6361     r = MsiRecordGetString(hrec, 1, buf, &size);
6362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6363     ok(!lstrcmp(buf, "This is a new 'string' ok"),
6364        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6365
6366     MsiCloseHandle(hrec);
6367
6368     r = MsiViewFetch(hview, &hrec);
6369     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6370
6371     MsiViewClose(hview);
6372     MsiCloseHandle(hview);
6373     MsiCloseHandle(hdb);
6374     DeleteFileA(msifile);
6375 }
6376
6377 static void test_carriagereturn(void)
6378 {
6379     MSIHANDLE hdb, hview, hrec;
6380     const char *query;
6381     char buf[MAX_PATH];
6382     UINT r;
6383     DWORD size;
6384
6385     DeleteFile(msifile);
6386
6387     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6389
6390     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6391     r = run_query(hdb, 0, query);
6392     ok(r == ERROR_BAD_QUERY_SYNTAX,
6393        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6394
6395     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6396     r = run_query(hdb, 0, query);
6397     ok(r == ERROR_BAD_QUERY_SYNTAX,
6398        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6399
6400     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6401     r = run_query(hdb, 0, query);
6402     ok(r == ERROR_BAD_QUERY_SYNTAX,
6403        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6404
6405     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6406     r = run_query(hdb, 0, query);
6407     ok(r == ERROR_BAD_QUERY_SYNTAX,
6408        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6409
6410     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6411     r = run_query(hdb, 0, query);
6412     ok(r == ERROR_BAD_QUERY_SYNTAX,
6413        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6414
6415     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6416     r = run_query(hdb, 0, query);
6417     ok(r == ERROR_BAD_QUERY_SYNTAX,
6418        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6419
6420     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6421     r = run_query(hdb, 0, query);
6422     ok(r == ERROR_BAD_QUERY_SYNTAX,
6423        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6424
6425     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6426     r = run_query(hdb, 0, query);
6427     ok(r == ERROR_BAD_QUERY_SYNTAX,
6428        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6429
6430     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6431     r = run_query(hdb, 0, query);
6432     ok(r == ERROR_BAD_QUERY_SYNTAX,
6433        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6434
6435     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6436     r = run_query(hdb, 0, query);
6437     ok(r == ERROR_BAD_QUERY_SYNTAX,
6438        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6439
6440     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6441     r = run_query(hdb, 0, query);
6442     ok(r == ERROR_BAD_QUERY_SYNTAX,
6443        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6444
6445     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6446     r = run_query(hdb, 0, query);
6447     ok(r == ERROR_BAD_QUERY_SYNTAX,
6448        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6449
6450     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6451     r = run_query(hdb, 0, query);
6452     ok(r == ERROR_BAD_QUERY_SYNTAX,
6453        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6454
6455     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6456     r = run_query(hdb, 0, query);
6457     ok(r == ERROR_BAD_QUERY_SYNTAX,
6458        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6459
6460     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6461     r = run_query(hdb, 0, query);
6462     ok(r == ERROR_BAD_QUERY_SYNTAX,
6463        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6464
6465     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6466     r = run_query(hdb, 0, query);
6467     ok(r == ERROR_BAD_QUERY_SYNTAX,
6468        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6469
6470     query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6471     r = run_query(hdb, 0, query);
6472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6473
6474     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6475     r = run_query(hdb, 0, query);
6476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6477
6478     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6479     r = run_query(hdb, 0, query);
6480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6481
6482     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6483     r = run_query(hdb, 0, query);
6484     ok(r == ERROR_BAD_QUERY_SYNTAX,
6485        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6486
6487     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6488     r = run_query(hdb, 0, query);
6489     ok(r == ERROR_BAD_QUERY_SYNTAX,
6490        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6491
6492     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6493     r = run_query(hdb, 0, query);
6494     ok(r == ERROR_BAD_QUERY_SYNTAX,
6495        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6496
6497     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6498     r = run_query(hdb, 0, query);
6499     ok(r == ERROR_BAD_QUERY_SYNTAX,
6500        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6501
6502     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6503     r = run_query(hdb, 0, query);
6504     ok(r == ERROR_BAD_QUERY_SYNTAX,
6505        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6506
6507     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6508     r = run_query(hdb, 0, query);
6509     ok(r == ERROR_BAD_QUERY_SYNTAX,
6510        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6511
6512     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6513     r = run_query(hdb, 0, query);
6514     ok(r == ERROR_BAD_QUERY_SYNTAX,
6515        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6516
6517     query = "SELECT * FROM `_Tables`";
6518     r = MsiDatabaseOpenView(hdb, query, &hview);
6519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6520     r = MsiViewExecute(hview, 0);
6521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6522
6523     r = MsiViewFetch(hview, &hrec);
6524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6525
6526     size = MAX_PATH;
6527     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6529     ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6530
6531     MsiCloseHandle(hrec);
6532
6533     r = MsiViewFetch(hview, &hrec);
6534     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6535
6536     size = MAX_PATH;
6537     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6539     ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6540
6541     MsiCloseHandle(hrec);
6542
6543     r = MsiViewFetch(hview, &hrec);
6544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6545
6546     size = MAX_PATH;
6547     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6549     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6550
6551     MsiCloseHandle(hrec);
6552
6553     r = MsiViewFetch(hview, &hrec);
6554     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6555
6556     MsiViewClose(hview);
6557     MsiCloseHandle(hview);
6558
6559     MsiCloseHandle(hdb);
6560     DeleteFileA(msifile);
6561 }
6562
6563 static void test_noquotes(void)
6564 {
6565     MSIHANDLE hdb, hview, hrec;
6566     const char *query;
6567     char buf[MAX_PATH];
6568     UINT r;
6569     DWORD size;
6570
6571     DeleteFile(msifile);
6572
6573     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6575
6576     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6577     r = run_query(hdb, 0, query);
6578     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6579
6580     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6581     r = run_query(hdb, 0, query);
6582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6583
6584     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6585     r = run_query(hdb, 0, query);
6586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6587
6588     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6589     r = run_query(hdb, 0, query);
6590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6591
6592     query = "SELECT * FROM `_Tables`";
6593     r = MsiDatabaseOpenView(hdb, query, &hview);
6594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6595     r = MsiViewExecute(hview, 0);
6596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6597
6598     r = MsiViewFetch(hview, &hrec);
6599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6600
6601     size = MAX_PATH;
6602     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6604     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6605
6606     MsiCloseHandle(hrec);
6607
6608     r = MsiViewFetch(hview, &hrec);
6609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6610
6611     size = MAX_PATH;
6612     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6614     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6615
6616     MsiCloseHandle(hrec);
6617
6618     r = MsiViewFetch(hview, &hrec);
6619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6620
6621     size = MAX_PATH;
6622     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6624     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6625
6626     MsiCloseHandle(hrec);
6627
6628     r = MsiViewFetch(hview, &hrec);
6629     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6630
6631     MsiViewClose(hview);
6632     MsiCloseHandle(hview);
6633
6634     query = "SELECT * FROM `_Columns`";
6635     r = MsiDatabaseOpenView(hdb, query, &hview);
6636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6637     r = MsiViewExecute(hview, 0);
6638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6639
6640     r = MsiViewFetch(hview, &hrec);
6641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6642
6643     size = MAX_PATH;
6644     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6646     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6647
6648     r = MsiRecordGetInteger(hrec, 2);
6649     ok(r == 1, "Expected 1, got %d\n", r);
6650
6651     size = MAX_PATH;
6652     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6654     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6655
6656     MsiCloseHandle(hrec);
6657
6658     r = MsiViewFetch(hview, &hrec);
6659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6660
6661     size = MAX_PATH;
6662     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6664     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6665
6666     r = MsiRecordGetInteger(hrec, 2);
6667     ok(r == 1, "Expected 1, got %d\n", r);
6668
6669     size = MAX_PATH;
6670     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6672     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6673
6674     MsiCloseHandle(hrec);
6675
6676     r = MsiViewFetch(hview, &hrec);
6677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6678
6679     size = MAX_PATH;
6680     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6682     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6683
6684     r = MsiRecordGetInteger(hrec, 2);
6685     ok(r == 1, "Expected 1, got %d\n", r);
6686
6687     size = MAX_PATH;
6688     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6690     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6691
6692     MsiCloseHandle(hrec);
6693
6694     r = MsiViewFetch(hview, &hrec);
6695     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6696
6697     MsiViewClose(hview);
6698     MsiCloseHandle(hview);
6699
6700     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
6701     r = run_query(hdb, 0, query);
6702     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6703
6704     query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
6705     r = run_query(hdb, 0, query);
6706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6707
6708     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
6709     r = run_query(hdb, 0, query);
6710     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6711
6712     query = "SELECT * FROM Table WHERE `A` = 'hi'";
6713     r = run_query(hdb, 0, query);
6714     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6715
6716     query = "SELECT * FROM `Table` WHERE `A` = hi";
6717     r = run_query(hdb, 0, query);
6718     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6719
6720     query = "SELECT * FROM Table";
6721     r = run_query(hdb, 0, query);
6722     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6723
6724     query = "SELECT * FROM Table2";
6725     r = MsiDatabaseOpenView(hdb, query, &hview);
6726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6727     r = MsiViewExecute(hview, 0);
6728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6729
6730     r = MsiViewFetch(hview, &hrec);
6731     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6732
6733     MsiViewClose(hview);
6734     MsiCloseHandle(hview);
6735
6736     query = "SELECT * FROM `Table` WHERE A = 'hi'";
6737     r = MsiDatabaseOpenView(hdb, query, &hview);
6738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6739     r = MsiViewExecute(hview, 0);
6740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6741
6742     r = MsiViewFetch(hview, &hrec);
6743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6744
6745     size = MAX_PATH;
6746     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6748     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
6749
6750     MsiCloseHandle(hrec);
6751
6752     r = MsiViewFetch(hview, &hrec);
6753     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6754
6755     MsiViewClose(hview);
6756     MsiCloseHandle(hview);
6757     MsiCloseHandle(hdb);
6758     DeleteFileA(msifile);
6759 }
6760
6761 static void read_file_data(LPCSTR filename, LPSTR buffer)
6762 {
6763     HANDLE file;
6764     DWORD read;
6765
6766     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
6767     ZeroMemory(buffer, MAX_PATH);
6768     ReadFile(file, buffer, MAX_PATH, &read, NULL);
6769     CloseHandle(file);
6770 }
6771
6772 static void test_forcecodepage(void)
6773 {
6774     MSIHANDLE hdb;
6775     const char *query;
6776     char buffer[MAX_PATH];
6777     UINT r;
6778
6779     DeleteFile(msifile);
6780
6781     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6783
6784     query = "SELECT * FROM `_ForceCodepage`";
6785     r = run_query(hdb, 0, query);
6786     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6787
6788     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6789     r = run_query(hdb, 0, query);
6790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6791
6792     query = "SELECT * FROM `_ForceCodepage`";
6793     r = run_query(hdb, 0, query);
6794     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6795
6796     r = MsiDatabaseCommit(hdb);
6797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6798
6799     query = "SELECT * FROM `_ForceCodepage`";
6800     r = run_query(hdb, 0, query);
6801     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6802
6803     MsiCloseHandle(hdb);
6804
6805     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb);
6806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6807
6808     query = "SELECT * FROM `_ForceCodepage`";
6809     r = run_query(hdb, 0, query);
6810     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6811
6812     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
6813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6814
6815     read_file_data("forcecodepage.idt", buffer);
6816     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
6817        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"", buffer);
6818
6819     MsiCloseHandle(hdb);
6820     DeleteFileA(msifile);
6821     DeleteFileA("forcecodepage.idt");
6822 }
6823
6824 static void test_viewmodify_refresh(void)
6825 {
6826     MSIHANDLE hdb, hview, hrec;
6827     const char *query;
6828     char buffer[MAX_PATH];
6829     UINT r;
6830     DWORD size;
6831
6832     DeleteFile(msifile);
6833
6834     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6836
6837     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
6838     r = run_query(hdb, 0, query);
6839     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6840
6841     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
6842     r = run_query(hdb, 0, query);
6843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6844
6845     query = "SELECT * FROM `Table`";
6846     r = MsiDatabaseOpenView(hdb, query, &hview);
6847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6848     r = MsiViewExecute(hview, 0);
6849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6850
6851     r = MsiViewFetch(hview, &hrec);
6852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6853
6854     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
6855     r = run_query(hdb, 0, query);
6856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6857
6858     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6860
6861     size = MAX_PATH;
6862     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
6863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6864     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
6865     ok(size == 2, "Expected 2, got %d\n", size);
6866
6867     r = MsiRecordGetInteger(hrec, 2);
6868     ok(r == 2, "Expected 2, got %d\n", r);
6869
6870     MsiCloseHandle(hrec);
6871     MsiViewClose(hview);
6872     MsiCloseHandle(hview);
6873
6874     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
6875     r = run_query(hdb, 0, query);
6876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6877
6878     query = "SELECT * FROM `Table` WHERE `B` = 3";
6879     r = MsiDatabaseOpenView(hdb, query, &hview);
6880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6881     r = MsiViewExecute(hview, 0);
6882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6883
6884     r = MsiViewFetch(hview, &hrec);
6885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6886
6887     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
6888     r = run_query(hdb, 0, query);
6889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6890
6891     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
6892     r = run_query(hdb, 0, query);
6893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6894
6895     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6897
6898     size = MAX_PATH;
6899     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
6900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6901     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
6902     ok(size == 5, "Expected 5, got %d\n", size);
6903
6904     r = MsiRecordGetInteger(hrec, 2);
6905     ok(r == 2, "Expected 2, got %d\n", r);
6906
6907     MsiCloseHandle(hrec);
6908     MsiViewClose(hview);
6909     MsiCloseHandle(hview);
6910     MsiCloseHandle(hdb);
6911     DeleteFileA(msifile);
6912 }
6913
6914 static void test_where_viewmodify(void)
6915 {
6916     MSIHANDLE hdb, hview, hrec;
6917     const char *query;
6918     UINT r;
6919
6920     DeleteFile(msifile);
6921
6922     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6924
6925     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
6926     r = run_query(hdb, 0, query);
6927     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6928
6929     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
6930     r = run_query(hdb, 0, query);
6931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6932
6933     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
6934     r = run_query(hdb, 0, query);
6935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6936
6937     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
6938     r = run_query(hdb, 0, query);
6939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6940
6941     /* `B` = 3 doesn't match, but the view shouldn't be executed */
6942     query = "SELECT * FROM `Table` WHERE `B` = 3";
6943     r = MsiDatabaseOpenView(hdb, query, &hview);
6944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6945
6946     hrec = MsiCreateRecord(2);
6947     MsiRecordSetInteger(hrec, 1, 7);
6948     MsiRecordSetInteger(hrec, 2, 8);
6949
6950     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6952
6953     MsiCloseHandle(hrec);
6954     MsiViewClose(hview);
6955     MsiCloseHandle(hview);
6956
6957     query = "SELECT * FROM `Table` WHERE `A` = 7";
6958     r = MsiDatabaseOpenView(hdb, query, &hview);
6959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6960     r = MsiViewExecute(hview, 0);
6961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6962
6963     r = MsiViewFetch(hview, &hrec);
6964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6965
6966     r = MsiRecordGetInteger(hrec, 1);
6967     ok(r == 7, "Expected 7, got %d\n", r);
6968
6969     r = MsiRecordGetInteger(hrec, 2);
6970     ok(r == 8, "Expected 8, got %d\n", r);
6971
6972     MsiRecordSetInteger(hrec, 2, 9);
6973
6974     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
6975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6976
6977     MsiCloseHandle(hrec);
6978     MsiViewClose(hview);
6979     MsiCloseHandle(hview);
6980
6981     query = "SELECT * FROM `Table` WHERE `A` = 7";
6982     r = MsiDatabaseOpenView(hdb, query, &hview);
6983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6984     r = MsiViewExecute(hview, 0);
6985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6986
6987     r = MsiViewFetch(hview, &hrec);
6988     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6989
6990     r = MsiRecordGetInteger(hrec, 1);
6991     ok(r == 7, "Expected 7, got %d\n", r);
6992
6993     r = MsiRecordGetInteger(hrec, 2);
6994     ok(r == 9, "Expected 9, got %d\n", r);
6995
6996     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
6997     r = run_query(hdb, 0, query);
6998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6999
7000     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7002
7003     r = MsiRecordGetInteger(hrec, 1);
7004     ok(r == 7, "Expected 7, got %d\n", r);
7005
7006     r = MsiRecordGetInteger(hrec, 2);
7007     ok(r == 10, "Expected 10, got %d\n", r);
7008
7009     MsiCloseHandle(hrec);
7010     MsiViewClose(hview);
7011     MsiCloseHandle(hview);
7012     MsiCloseHandle(hdb);
7013 }
7014
7015 static BOOL create_storage(LPCSTR name)
7016 {
7017     WCHAR nameW[MAX_PATH];
7018     IStorage *stg;
7019     IStream *stm;
7020     HRESULT hr;
7021     DWORD count;
7022     BOOL res = FALSE;
7023
7024     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7025     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7026                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7027     if (FAILED(hr))
7028         return FALSE;
7029
7030     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7031                                0, 0, &stm);
7032     if (FAILED(hr))
7033         goto done;
7034
7035     hr = IStream_Write(stm, "stgdata", 8, &count);
7036     if (SUCCEEDED(hr))
7037         res = TRUE;
7038
7039 done:
7040     IStream_Release(stm);
7041     IStorage_Release(stg);
7042
7043     return res;
7044 }
7045
7046 static void test_storages_table(void)
7047 {
7048     MSIHANDLE hdb, hview, hrec;
7049     IStorage *stg, *inner;
7050     IStream *stm;
7051     char file[MAX_PATH];
7052     char buf[MAX_PATH];
7053     WCHAR name[MAX_PATH];
7054     LPCSTR query;
7055     HRESULT hr;
7056     DWORD size;
7057     UINT r;
7058
7059     hdb = create_db();
7060     ok(hdb, "failed to create db\n");
7061
7062     r = MsiDatabaseCommit(hdb);
7063     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7064
7065     MsiCloseHandle(hdb);
7066
7067     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
7068     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7069
7070     /* check the column types */
7071     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7072     ok(hrec, "failed to get column info hrecord\n");
7073     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7074     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7075
7076     MsiCloseHandle(hrec);
7077
7078     /* now try the names */
7079     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7080     ok(hrec, "failed to get column info hrecord\n");
7081     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7082     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7083
7084     MsiCloseHandle(hrec);
7085
7086     create_storage("storage.bin");
7087
7088     hrec = MsiCreateRecord(2);
7089     MsiRecordSetString(hrec, 1, "stgname");
7090
7091     r = MsiRecordSetStream(hrec, 2, "storage.bin");
7092     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7093
7094     DeleteFileA("storage.bin");
7095
7096     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7097     r = MsiDatabaseOpenView(hdb, query, &hview);
7098     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7099
7100     r = MsiViewExecute(hview, hrec);
7101     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7102
7103     MsiCloseHandle(hrec);
7104     MsiViewClose(hview);
7105     MsiCloseHandle(hview);
7106
7107     query = "SELECT `Name`, `Data` FROM `_Storages`";
7108     r = MsiDatabaseOpenView(hdb, query, &hview);
7109     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7110
7111     r = MsiViewExecute(hview, 0);
7112     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7113
7114     r = MsiViewFetch(hview, &hrec);
7115     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7116
7117     size = MAX_PATH;
7118     r = MsiRecordGetString(hrec, 1, file, &size);
7119     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7120     ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7121
7122     size = MAX_PATH;
7123     lstrcpyA(buf, "apple");
7124     r = MsiRecordReadStream(hrec, 2, buf, &size);
7125     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7126     ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7127     ok(size == 0, "Expected 0, got %d\n", size);
7128
7129     MsiCloseHandle(hrec);
7130
7131     r = MsiViewFetch(hview, &hrec);
7132     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7133
7134     MsiViewClose(hview);
7135     MsiCloseHandle(hview);
7136
7137     MsiDatabaseCommit(hdb);
7138     MsiCloseHandle(hdb);
7139
7140     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7141     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7142                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7143     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7144     ok(stg != NULL, "Expected non-NULL storage\n");
7145
7146     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7147     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7148                               NULL, 0, &inner);
7149     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7150     ok(inner != NULL, "Expected non-NULL storage\n");
7151
7152     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7153     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7154     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7155     ok(stm != NULL, "Expected non-NULL stream\n");
7156
7157     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7158     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7159     ok(size == 8, "Expected 8, got %d\n", size);
7160     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7161
7162     IStream_Release(stm);
7163     IStorage_Release(inner);
7164
7165     IStorage_Release(stg);
7166     DeleteFileA(msifile);
7167 }
7168
7169 static void test_dbtopackage(void)
7170 {
7171     MSIHANDLE hdb, hpkg;
7172     CHAR package[10];
7173     CHAR buf[MAX_PATH];
7174     DWORD size;
7175     UINT r;
7176
7177     /* create an empty database, transact mode */
7178     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7179     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7180
7181     set_summary_info(hdb);
7182
7183     r = create_directory_table(hdb);
7184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7185
7186     r = create_custom_action_table(hdb);
7187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7188
7189     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7191
7192     sprintf(package, "#%i", hdb);
7193     r = MsiOpenPackage(package, &hpkg);
7194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7195
7196     /* property is not set yet */
7197     size = MAX_PATH;
7198     lstrcpyA(buf, "kiwi");
7199     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7201     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7202     ok(size == 0, "Expected 0, got %d\n", size);
7203
7204     /* run the custom action to set the property */
7205     r = MsiDoAction(hpkg, "SetProp");
7206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7207
7208     /* property is now set */
7209     size = MAX_PATH;
7210     lstrcpyA(buf, "kiwi");
7211     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7213     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7214     ok(size == 5, "Expected 5, got %d\n", size);
7215
7216     MsiCloseHandle(hpkg);
7217
7218     /* reset the package */
7219     r = MsiOpenPackage(package, &hpkg);
7220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7221
7222     /* property is not set anymore */
7223     size = MAX_PATH;
7224     lstrcpyA(buf, "kiwi");
7225     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7227     todo_wine
7228     {
7229         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7230         ok(size == 0, "Expected 0, got %d\n", size);
7231     }
7232
7233     MsiCloseHandle(hdb);
7234     MsiCloseHandle(hpkg);
7235
7236     /* create an empty database, direct mode */
7237     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
7238     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7239
7240     set_summary_info(hdb);
7241
7242     r = create_directory_table(hdb);
7243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7244
7245     r = create_custom_action_table(hdb);
7246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7247
7248     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7250
7251     sprintf(package, "#%i", hdb);
7252     r = MsiOpenPackage(package, &hpkg);
7253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7254
7255     /* property is not set yet */
7256     size = MAX_PATH;
7257     lstrcpyA(buf, "kiwi");
7258     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7260     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7261     ok(size == 0, "Expected 0, got %d\n", size);
7262
7263     /* run the custom action to set the property */
7264     r = MsiDoAction(hpkg, "SetProp");
7265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7266
7267     /* property is now set */
7268     size = MAX_PATH;
7269     lstrcpyA(buf, "kiwi");
7270     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7272     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7273     ok(size == 5, "Expected 5, got %d\n", size);
7274
7275     MsiCloseHandle(hpkg);
7276
7277     /* reset the package */
7278     r = MsiOpenPackage(package, &hpkg);
7279     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7280
7281     /* property is not set anymore */
7282     size = MAX_PATH;
7283     lstrcpyA(buf, "kiwi");
7284     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7286     todo_wine
7287     {
7288         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7289         ok(size == 0, "Expected 0, got %d\n", size);
7290     }
7291
7292     MsiCloseHandle(hdb);
7293     MsiCloseHandle(hpkg);
7294     DeleteFileA(msifile);
7295 }
7296
7297 static void test_droptable(void)
7298 {
7299     MSIHANDLE hdb, hview, hrec;
7300     CHAR buf[MAX_PATH];
7301     LPCSTR query;
7302     DWORD size;
7303     UINT r;
7304
7305     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7307
7308     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7309     r = run_query(hdb, 0, query);
7310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7311
7312     query = "SELECT * FROM `One`";
7313     r = do_query(hdb, query, &hrec);
7314     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7315
7316     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7317     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7319     r = MsiViewExecute(hview, 0);
7320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7321
7322     r = MsiViewFetch(hview, &hrec);
7323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7324
7325     size = MAX_PATH;
7326     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7329
7330     MsiCloseHandle(hrec);
7331     MsiViewClose(hview);
7332     MsiCloseHandle(hview);
7333
7334     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7335     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7337     r = MsiViewExecute(hview, 0);
7338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7339
7340     r = MsiViewFetch(hview, &hrec);
7341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7342
7343     size = MAX_PATH;
7344     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7346     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7347
7348     r = MsiRecordGetInteger(hrec, 2);
7349     ok(r == 1, "Expected 1, got %d\n", r);
7350
7351     size = MAX_PATH;
7352     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7354     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7355
7356     MsiCloseHandle(hrec);
7357
7358     r = MsiViewFetch(hview, &hrec);
7359     ok(r == ERROR_NO_MORE_ITEMS,
7360        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7361
7362     MsiViewClose(hview);
7363     MsiCloseHandle(hview);
7364
7365     query = "DROP `One`";
7366     r = run_query(hdb, 0, query);
7367     ok(r == ERROR_BAD_QUERY_SYNTAX,
7368        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7369
7370     query = "DROP TABLE";
7371     r = run_query(hdb, 0, query);
7372     ok(r == ERROR_BAD_QUERY_SYNTAX,
7373        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7374
7375     query = "DROP TABLE `One`";
7376     hview = 0;
7377     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7379     r = MsiViewExecute(hview, 0);
7380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7381
7382     r = MsiViewFetch(hview, &hrec);
7383     ok(r == ERROR_FUNCTION_FAILED,
7384        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7385
7386     MsiViewClose(hview);
7387     MsiCloseHandle(hview);
7388
7389     query = "SELECT * FROM `IDontExist`";
7390     r = do_query(hdb, query, &hrec);
7391     ok(r == ERROR_BAD_QUERY_SYNTAX,
7392        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7393
7394     query = "SELECT * FROM `One`";
7395     r = do_query(hdb, query, &hrec);
7396     ok(r == ERROR_BAD_QUERY_SYNTAX,
7397        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7398
7399     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7400     r = run_query(hdb, 0, query);
7401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7402
7403     query = "DROP TABLE One";
7404     r = run_query(hdb, 0, query);
7405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7406
7407     query = "SELECT * FROM `One`";
7408     r = do_query(hdb, query, &hrec);
7409     ok(r == ERROR_BAD_QUERY_SYNTAX,
7410        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7411
7412     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7413     r = do_query(hdb, query, &hrec);
7414     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7415
7416     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7417     r = do_query(hdb, query, &hrec);
7418     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7419
7420     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7421     r = run_query(hdb, 0, query);
7422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7423
7424     query = "SELECT * FROM `One`";
7425     r = do_query(hdb, query, &hrec);
7426     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7427
7428     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7429     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7431     r = MsiViewExecute(hview, 0);
7432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7433
7434     r = MsiViewFetch(hview, &hrec);
7435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7436
7437     size = MAX_PATH;
7438     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7440     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7441
7442     MsiCloseHandle(hrec);
7443     MsiViewClose(hview);
7444     MsiCloseHandle(hview);
7445
7446     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7447     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7449     r = MsiViewExecute(hview, 0);
7450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7451
7452     r = MsiViewFetch(hview, &hrec);
7453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7454
7455     size = MAX_PATH;
7456     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7458     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7459
7460     r = MsiRecordGetInteger(hrec, 2);
7461     ok(r == 1, "Expected 1, got %d\n", r);
7462
7463     size = MAX_PATH;
7464     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7466     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7467
7468     MsiCloseHandle(hrec);
7469
7470     r = MsiViewFetch(hview, &hrec);
7471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7472
7473     size = MAX_PATH;
7474     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7475     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7476     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7477
7478     r = MsiRecordGetInteger(hrec, 2);
7479     ok(r == 2, "Expected 2, got %d\n", r);
7480
7481     size = MAX_PATH;
7482     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7484     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7485
7486     MsiCloseHandle(hrec);
7487
7488     r = MsiViewFetch(hview, &hrec);
7489     ok(r == ERROR_NO_MORE_ITEMS,
7490        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7491
7492     MsiViewClose(hview);
7493     MsiCloseHandle(hview);
7494
7495     query = "DROP TABLE One";
7496     r = run_query(hdb, 0, query);
7497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7498
7499     query = "SELECT * FROM `One`";
7500     r = do_query(hdb, query, &hrec);
7501     ok(r == ERROR_BAD_QUERY_SYNTAX,
7502        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7503
7504     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7505     r = do_query(hdb, query, &hrec);
7506     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7507
7508     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7509     r = do_query(hdb, query, &hrec);
7510     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7511
7512     MsiCloseHandle(hdb);
7513     DeleteFileA(msifile);
7514 }
7515
7516 static void test_dbmerge(void)
7517 {
7518     MSIHANDLE hdb, href, hview, hrec;
7519     CHAR buf[MAX_PATH];
7520     LPCSTR query;
7521     DWORD size;
7522     UINT r;
7523
7524     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7526
7527     r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
7528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7529
7530     /* hDatabase is invalid */
7531     r = MsiDatabaseMergeA(0, href, "MergeErrors");
7532     ok(r == ERROR_INVALID_HANDLE,
7533        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7534
7535     /* hDatabaseMerge is invalid */
7536     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7537     ok(r == ERROR_INVALID_HANDLE,
7538        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7539
7540     /* szTableName is NULL */
7541     r = MsiDatabaseMergeA(hdb, href, NULL);
7542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7543
7544     /* szTableName is empty */
7545     r = MsiDatabaseMergeA(hdb, href, "");
7546     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7547
7548     /* both DBs empty, szTableName is valid */
7549     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7551
7552     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7553     r = run_query(hdb, 0, query);
7554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7555
7556     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7557     r = run_query(href, 0, query);
7558     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7559
7560     /* column types don't match */
7561     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7562     ok(r == ERROR_DATATYPE_MISMATCH,
7563        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7564
7565     /* nothing in MergeErrors */
7566     query = "SELECT * FROM `MergeErrors`";
7567     r = do_query(hdb, query, &hrec);
7568     ok(r == ERROR_BAD_QUERY_SYNTAX,
7569        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7570
7571     query = "DROP TABLE `One`";
7572     r = run_query(hdb, 0, query);
7573     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7574
7575     query = "DROP TABLE `One`";
7576     r = run_query(href, 0, query);
7577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7578
7579     query = "CREATE TABLE `One` ( "
7580         "`A` CHAR(72), "
7581         "`B` CHAR(56), "
7582         "`C` CHAR(64) LOCALIZABLE, "
7583         "`D` LONGCHAR, "
7584         "`E` CHAR(72) NOT NULL, "
7585         "`F` CHAR(56) NOT NULL, "
7586         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7587         "`H` LONGCHAR NOT NULL "
7588         "PRIMARY KEY `A` )";
7589     r = run_query(hdb, 0, query);
7590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7591
7592     query = "CREATE TABLE `One` ( "
7593         "`A` CHAR(64), "
7594         "`B` CHAR(64), "
7595         "`C` CHAR(64), "
7596         "`D` CHAR(64), "
7597         "`E` CHAR(64) NOT NULL, "
7598         "`F` CHAR(64) NOT NULL, "
7599         "`G` CHAR(64) NOT NULL, "
7600         "`H` CHAR(64) NOT NULL "
7601         "PRIMARY KEY `A` )";
7602     r = run_query(href, 0, query);
7603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7604
7605     /* column sting types don't match exactly */
7606     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7607     ok(r == ERROR_SUCCESS,
7608        "Expected ERROR_SUCCESS, got %d\n", r);
7609
7610     /* nothing in MergeErrors */
7611     query = "SELECT * FROM `MergeErrors`";
7612     r = do_query(hdb, query, &hrec);
7613     ok(r == ERROR_BAD_QUERY_SYNTAX,
7614        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7615
7616     query = "DROP TABLE `One`";
7617     r = run_query(hdb, 0, query);
7618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7619
7620     query = "DROP TABLE `One`";
7621     r = run_query(href, 0, query);
7622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7623
7624     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7625     r = run_query(hdb, 0, query);
7626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7627
7628     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
7629     r = run_query(href, 0, query);
7630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7631
7632     /* column names don't match */
7633     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7634     ok(r == ERROR_DATATYPE_MISMATCH,
7635        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7636
7637     /* nothing in MergeErrors */
7638     query = "SELECT * FROM `MergeErrors`";
7639     r = do_query(hdb, query, &hrec);
7640     ok(r == ERROR_BAD_QUERY_SYNTAX,
7641        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7642
7643     query = "DROP TABLE `One`";
7644     r = run_query(hdb, 0, query);
7645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7646
7647     query = "DROP TABLE `One`";
7648     r = run_query(href, 0, query);
7649     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7650
7651     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7652     r = run_query(hdb, 0, query);
7653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7654
7655     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
7656     r = run_query(href, 0, query);
7657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7658
7659     /* primary keys don't match */
7660     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7661     ok(r == ERROR_DATATYPE_MISMATCH,
7662        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7663
7664     /* nothing in MergeErrors */
7665     query = "SELECT * FROM `MergeErrors`";
7666     r = do_query(hdb, query, &hrec);
7667     ok(r == ERROR_BAD_QUERY_SYNTAX,
7668        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7669
7670     query = "DROP TABLE `One`";
7671     r = run_query(hdb, 0, query);
7672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7673
7674     query = "DROP TABLE `One`";
7675     r = run_query(href, 0, query);
7676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7677
7678     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7679     r = run_query(hdb, 0, query);
7680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7681
7682     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
7683     r = run_query(href, 0, query);
7684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7685
7686     /* number of primary keys doesn't match */
7687     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7688     ok(r == ERROR_DATATYPE_MISMATCH,
7689        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7690
7691     /* nothing in MergeErrors */
7692     query = "SELECT * FROM `MergeErrors`";
7693     r = do_query(hdb, query, &hrec);
7694     ok(r == ERROR_BAD_QUERY_SYNTAX,
7695        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7696
7697     query = "DROP TABLE `One`";
7698     r = run_query(hdb, 0, query);
7699     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7700
7701     query = "DROP TABLE `One`";
7702     r = run_query(href, 0, query);
7703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7704
7705     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
7706     r = run_query(hdb, 0, query);
7707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7708
7709     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7710     r = run_query(href, 0, query);
7711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7712
7713     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
7714     r = run_query(href, 0, query);
7715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7716
7717     /* number of columns doesn't match */
7718     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7720
7721     query = "SELECT * FROM `One`";
7722     r = do_query(hdb, query, &hrec);
7723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7724
7725     r = MsiRecordGetInteger(hrec, 1);
7726     ok(r == 1, "Expected 1, got %d\n", r);
7727
7728     r = MsiRecordGetInteger(hrec, 2);
7729     ok(r == 2, "Expected 2, got %d\n", r);
7730
7731     r = MsiRecordGetInteger(hrec, 3);
7732     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
7733
7734     MsiCloseHandle(hrec);
7735
7736     /* nothing in MergeErrors */
7737     query = "SELECT * FROM `MergeErrors`";
7738     r = do_query(hdb, query, &hrec);
7739     ok(r == ERROR_BAD_QUERY_SYNTAX,
7740        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7741
7742     query = "DROP TABLE `One`";
7743     r = run_query(hdb, 0, query);
7744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7745
7746     query = "DROP TABLE `One`";
7747     r = run_query(href, 0, query);
7748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7749
7750     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7751     r = run_query(hdb, 0, query);
7752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7753
7754     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
7755     r = run_query(href, 0, query);
7756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7757
7758     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
7759     r = run_query(href, 0, query);
7760     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7761
7762     /* number of columns doesn't match */
7763     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7764     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7765
7766     query = "SELECT * FROM `One`";
7767     r = do_query(hdb, query, &hrec);
7768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7769
7770     r = MsiRecordGetInteger(hrec, 1);
7771     ok(r == 1, "Expected 1, got %d\n", r);
7772
7773     r = MsiRecordGetInteger(hrec, 2);
7774     ok(r == 2, "Expected 2, got %d\n", r);
7775
7776     r = MsiRecordGetInteger(hrec, 3);
7777     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
7778
7779     MsiCloseHandle(hrec);
7780
7781     /* nothing in MergeErrors */
7782     query = "SELECT * FROM `MergeErrors`";
7783     r = do_query(hdb, query, &hrec);
7784     ok(r == ERROR_BAD_QUERY_SYNTAX,
7785        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7786
7787     query = "DROP TABLE `One`";
7788     r = run_query(hdb, 0, query);
7789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7790
7791     query = "DROP TABLE `One`";
7792     r = run_query(href, 0, query);
7793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7794
7795     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7796     r = run_query(hdb, 0, query);
7797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7798
7799     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
7800     r = run_query(hdb, 0, query);
7801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7802
7803     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
7804     r = run_query(hdb, 0, query);
7805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7806
7807     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7808     r = run_query(href, 0, query);
7809     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7810
7811     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
7812     r = run_query(href, 0, query);
7813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7814
7815     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
7816     r = run_query(href, 0, query);
7817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7818
7819     /* primary keys match, rows do not */
7820     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7821     ok(r == ERROR_FUNCTION_FAILED,
7822        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7823
7824     /* nothing in MergeErrors */
7825     query = "SELECT * FROM `MergeErrors`";
7826     r = do_query(hdb, query, &hrec);
7827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7828
7829     size = MAX_PATH;
7830     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7832     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7833
7834     r = MsiRecordGetInteger(hrec, 2);
7835     ok(r == 2, "Expected 2, got %d\n", r);
7836
7837     MsiCloseHandle(hrec);
7838
7839     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
7840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7841
7842     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
7843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7844
7845     size = MAX_PATH;
7846     r = MsiRecordGetString(hrec, 1, buf, &size);
7847     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
7848
7849     size = MAX_PATH;
7850     r = MsiRecordGetString(hrec, 2, buf, &size);
7851     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
7852        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
7853
7854     MsiCloseHandle(hrec);
7855
7856     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
7857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7858
7859     size = MAX_PATH;
7860     r = MsiRecordGetString(hrec, 1, buf, &size);
7861     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
7862
7863     size = MAX_PATH;
7864     r = MsiRecordGetString(hrec, 2, buf, &size);
7865     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
7866
7867     MsiCloseHandle(hrec);
7868     MsiViewClose(hview);
7869     MsiCloseHandle(hview);
7870
7871     query = "DROP TABLE `MergeErrors`";
7872     r = run_query(hdb, 0, query);
7873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7874
7875     query = "DROP TABLE `One`";
7876     r = run_query(hdb, 0, query);
7877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7878
7879     query = "DROP TABLE `One`";
7880     r = run_query(href, 0, query);
7881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7882
7883     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
7884     r = run_query(href, 0, query);
7885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7886
7887     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
7888     r = run_query(href, 0, query);
7889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7890
7891     /* table from merged database is not in target database */
7892     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7894
7895     query = "SELECT * FROM `One`";
7896     r = do_query(hdb, query, &hrec);
7897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7898
7899     r = MsiRecordGetInteger(hrec, 1);
7900     ok(r == 1, "Expected 1, got %d\n", r);
7901
7902     size = MAX_PATH;
7903     r = MsiRecordGetStringA(hrec, 2, buf, &size);
7904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7905     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7906
7907     MsiCloseHandle(hrec);
7908
7909     /* nothing in MergeErrors */
7910     query = "SELECT * FROM `MergeErrors`";
7911     r = do_query(hdb, query, &hrec);
7912     ok(r == ERROR_BAD_QUERY_SYNTAX,
7913        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7914
7915     query = "DROP TABLE `One`";
7916     r = run_query(hdb, 0, query);
7917     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7918
7919     query = "DROP TABLE `One`";
7920     r = run_query(href, 0, query);
7921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7922
7923     query = "CREATE TABLE `One` ( "
7924             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
7925     r = run_query(hdb, 0, query);
7926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7927
7928     query = "CREATE TABLE `One` ( "
7929             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
7930     r = run_query(href, 0, query);
7931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7932
7933     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7934     r = run_query(href, 0, query);
7935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7936
7937     /* primary key is string */
7938     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7940
7941     query = "SELECT * FROM `One`";
7942     r = do_query(hdb, query, &hrec);
7943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7944
7945     size = MAX_PATH;
7946     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7948     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7949
7950     r = MsiRecordGetInteger(hrec, 2);
7951     ok(r == 1, "Expected 1, got %d\n", r);
7952
7953     MsiCloseHandle(hrec);
7954
7955     /* nothing in MergeErrors */
7956     query = "SELECT * FROM `MergeErrors`";
7957     r = do_query(hdb, query, &hrec);
7958     ok(r == ERROR_BAD_QUERY_SYNTAX,
7959        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7960
7961     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7962
7963     GetCurrentDirectoryA(MAX_PATH, buf);
7964     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
7965     todo_wine
7966     {
7967         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7968     }
7969
7970     query = "DROP TABLE `One`";
7971     r = run_query(hdb, 0, query);
7972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7973
7974     query = "DROP TABLE `One`";
7975     r = run_query(href, 0, query);
7976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7977
7978     query = "CREATE TABLE `One` ( "
7979             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
7980     r = run_query(hdb, 0, query);
7981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7982
7983     query = "CREATE TABLE `One` ( "
7984             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
7985     r = run_query(href, 0, query);
7986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7987
7988     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
7989     r = run_query(href, 0, query);
7990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7991
7992     /* code page does not match */
7993     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7994     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7995
7996     query = "SELECT * FROM `One`";
7997     r = do_query(hdb, query, &hrec);
7998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7999
8000     r = MsiRecordGetInteger(hrec, 1);
8001     ok(r == 1, "Expected 1, got %d\n", r);
8002
8003     size = MAX_PATH;
8004     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8006     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8007
8008     MsiCloseHandle(hrec);
8009
8010     /* nothing in MergeErrors */
8011     query = "SELECT * FROM `MergeErrors`";
8012     r = do_query(hdb, query, &hrec);
8013     ok(r == ERROR_BAD_QUERY_SYNTAX,
8014        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8015
8016     query = "DROP TABLE `One`";
8017     r = run_query(hdb, 0, query);
8018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8019
8020     query = "DROP TABLE `One`";
8021     r = run_query(href, 0, query);
8022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8023
8024     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8025     r = run_query(hdb, 0, query);
8026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8027
8028     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8029     r = run_query(href, 0, query);
8030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8031
8032     create_file("binary.dat");
8033     hrec = MsiCreateRecord(1);
8034     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8035
8036     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8037     r = run_query(href, hrec, query);
8038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8039
8040     MsiCloseHandle(hrec);
8041
8042     /* binary data to merge */
8043     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8045
8046     query = "SELECT * FROM `One`";
8047     r = do_query(hdb, query, &hrec);
8048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8049
8050     r = MsiRecordGetInteger(hrec, 1);
8051     ok(r == 1, "Expected 1, got %d\n", r);
8052
8053     size = MAX_PATH;
8054     ZeroMemory(buf, MAX_PATH);
8055     r = MsiRecordReadStream(hrec, 2, buf, &size);
8056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8057     ok(!lstrcmpA(buf, "binary.dat\n"),
8058        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8059
8060     MsiCloseHandle(hrec);
8061
8062     /* nothing in MergeErrors */
8063     query = "SELECT * FROM `MergeErrors`";
8064     r = do_query(hdb, query, &hrec);
8065     ok(r == ERROR_BAD_QUERY_SYNTAX,
8066        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8067
8068     query = "DROP TABLE `One`";
8069     r = run_query(hdb, 0, query);
8070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8071
8072     query = "DROP TABLE `One`";
8073     r = run_query(href, 0, query);
8074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8075
8076     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8077     r = run_query(hdb, 0, query);
8078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8079     r = run_query(href, 0, query);
8080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8081
8082     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8083     r = run_query(href, 0, query);
8084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8085
8086     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8087     r = run_query(href, 0, query);
8088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8089
8090     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8092
8093     query = "SELECT * FROM `One`";
8094     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8096     r = MsiViewExecute(hview, 0);
8097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8098
8099     r = MsiViewFetch(hview, &hrec);
8100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8101
8102     r = MsiRecordGetInteger(hrec, 1);
8103     ok(r == 1, "Expected 1, got %d\n", r);
8104
8105     size = MAX_PATH;
8106     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8108     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8109
8110     MsiCloseHandle(hrec);
8111
8112     r = MsiViewFetch(hview, &hrec);
8113     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8114
8115     r = MsiRecordGetInteger(hrec, 1);
8116     ok(r == 2, "Expected 2, got %d\n", r);
8117
8118     size = MAX_PATH;
8119     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8120     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8121     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8122
8123     MsiCloseHandle(hrec);
8124
8125     r = MsiViewFetch(hview, &hrec);
8126     ok(r == ERROR_NO_MORE_ITEMS,
8127        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8128
8129     MsiViewClose(hview);
8130     MsiCloseHandle(hview);
8131
8132     MsiCloseHandle(hdb);
8133     MsiCloseHandle(href);
8134     DeleteFileA(msifile);
8135     DeleteFileA("refdb.msi");
8136     DeleteFileA("codepage.idt");
8137     DeleteFileA("binary.dat");
8138 }
8139
8140 static void test_select_with_tablenames(void)
8141 {
8142     MSIHANDLE hdb, view, rec;
8143     LPCSTR query;
8144     UINT r;
8145     int i;
8146
8147     int vals[4][2] = {
8148         {1,12},
8149         {4,12},
8150         {1,15},
8151         {4,15}};
8152
8153     hdb = create_db();
8154     ok(hdb, "failed to create db\n");
8155
8156     /* Build a pair of tables with the same column names, but unique data */
8157     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8158     r = run_query(hdb, 0, query);
8159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8160
8161     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8162     r = run_query(hdb, 0, query);
8163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8164
8165     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8166     r = run_query(hdb, 0, query);
8167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8168
8169     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8170     r = run_query(hdb, 0, query);
8171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8172
8173     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8174     r = run_query(hdb, 0, query);
8175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8176
8177     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8178     r = run_query(hdb, 0, query);
8179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8180
8181
8182     /* Test that selection based on prefixing the column with the table
8183      * actually selects the right data */
8184
8185     query = "SELECT T1.A, T2.B FROM T1,T2";
8186     r = MsiDatabaseOpenView(hdb, query, &view);
8187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8188     r = MsiViewExecute(view, 0);
8189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8190
8191     for (i = 0; i < 4; i++)
8192     {
8193         r = MsiViewFetch(view, &rec);
8194         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8195
8196         r = MsiRecordGetInteger(rec, 1);
8197         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8198
8199         r = MsiRecordGetInteger(rec, 2);
8200         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8201
8202         MsiCloseHandle(rec);
8203     }
8204
8205     r = MsiViewFetch(view, &rec);
8206     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8207
8208     MsiViewClose(view);
8209     MsiCloseHandle(view);
8210     MsiCloseHandle(hdb);
8211     DeleteFileA(msifile);
8212 }
8213
8214 UINT ordervals[6][3] =
8215 {
8216     { MSI_NULL_INTEGER, 12, 13 },
8217     { 1, 2, 3 },
8218     { 6, 4, 5 },
8219     { 8, 9, 7 },
8220     { 10, 11, MSI_NULL_INTEGER },
8221     { 14, MSI_NULL_INTEGER, 15 }
8222 };
8223
8224 static void test_insertorder(void)
8225 {
8226     MSIHANDLE hdb, view, rec;
8227     LPCSTR query;
8228     UINT r;
8229     int i;
8230
8231     hdb = create_db();
8232     ok(hdb, "failed to create db\n");
8233
8234     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8235     r = run_query(hdb, 0, query);
8236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8237
8238     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8239     r = run_query(hdb, 0, query);
8240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8241
8242     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8243     r = run_query(hdb, 0, query);
8244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8245
8246     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8247     r = run_query(hdb, 0, query);
8248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8249
8250     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8251     r = run_query(hdb, 0, query);
8252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8253
8254     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8255     r = run_query(hdb, 0, query);
8256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8257
8258     /* fails because the primary key already
8259      * has an MSI_NULL_INTEGER value set above
8260      */
8261     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8262     r = run_query(hdb, 0, query);
8263     ok(r == ERROR_FUNCTION_FAILED,
8264        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8265
8266     /* replicate the error where primary key is set twice */
8267     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8268     r = run_query(hdb, 0, query);
8269     ok(r == ERROR_FUNCTION_FAILED,
8270        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8271
8272     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8273     r = run_query(hdb, 0, query);
8274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8275
8276     query = "INSERT INTO `T` VALUES ( 16 )";
8277     r = run_query(hdb, 0, query);
8278     ok(r == ERROR_BAD_QUERY_SYNTAX,
8279        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8280
8281     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8282     r = run_query(hdb, 0, query);
8283     ok(r == ERROR_BAD_QUERY_SYNTAX,
8284        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8285
8286     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8287     r = run_query(hdb, 0, query);
8288     ok(r == ERROR_BAD_QUERY_SYNTAX,
8289        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8290
8291     query = "SELECT * FROM `T`";
8292     r = MsiDatabaseOpenView(hdb, query, &view);
8293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8294     r = MsiViewExecute(view, 0);
8295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8296
8297     for (i = 0; i < 6; i++)
8298     {
8299         r = MsiViewFetch(view, &rec);
8300         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8301
8302         r = MsiRecordGetInteger(rec, 1);
8303         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8304
8305         r = MsiRecordGetInteger(rec, 2);
8306         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8307
8308         r = MsiRecordGetInteger(rec, 3);
8309         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8310
8311         MsiCloseHandle(rec);
8312     }
8313
8314     r = MsiViewFetch(view, &rec);
8315     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8316
8317     MsiViewClose(view);
8318     MsiCloseHandle(view);
8319
8320     query = "DELETE FROM `T` WHERE `A` IS NULL";
8321     r = run_query(hdb, 0, query);
8322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8323
8324     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8325     r = run_query(hdb, 0, query);
8326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8327
8328     query = "SELECT * FROM `T`";
8329     r = MsiDatabaseOpenView(hdb, query, &view);
8330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8331     r = MsiViewExecute(view, 0);
8332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8333
8334     for (i = 0; i < 6; i++)
8335     {
8336         r = MsiViewFetch(view, &rec);
8337         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8338
8339         r = MsiRecordGetInteger(rec, 1);
8340         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8341
8342         r = MsiRecordGetInteger(rec, 2);
8343         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8344
8345         r = MsiRecordGetInteger(rec, 3);
8346         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8347
8348         MsiCloseHandle(rec);
8349     }
8350
8351     r = MsiViewFetch(view, &rec);
8352     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8353
8354     MsiViewClose(view);
8355     MsiCloseHandle(view);
8356     MsiCloseHandle(hdb);
8357     DeleteFileA(msifile);
8358 }
8359
8360 static void test_columnorder(void)
8361 {
8362     MSIHANDLE hdb, view, rec;
8363     char buf[MAX_PATH];
8364     LPCSTR query;
8365     DWORD sz;
8366     UINT r;
8367
8368     hdb = create_db();
8369     ok(hdb, "failed to create db\n");
8370
8371     /* Each column is a slot:
8372      * ---------------------
8373      * | B | C | A | E | D |
8374      * ---------------------
8375      *
8376      * When a column is selected as a primary key,
8377      * the column occupying the nth primary key slot is swapped
8378      * with the current position of the primary key in question:
8379      *
8380      * set primary key `D`
8381      * ---------------------    ---------------------
8382      * | B | C | A | E | D | -> | D | C | A | E | B |
8383      * ---------------------    ---------------------
8384      *
8385      * set primary key `E`
8386      * ---------------------    ---------------------
8387      * | D | C | A | E | B | -> | D | E | A | C | B |
8388      * ---------------------    ---------------------
8389      */
8390
8391     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8392             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8393             "PRIMARY KEY `D`, `E`)";
8394     r = run_query(hdb, 0, query);
8395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8396
8397     query = "SELECT * FROM `T`";
8398     r = MsiDatabaseOpenView(hdb, query, &view);
8399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8400
8401     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8403
8404     sz = MAX_PATH;
8405     lstrcpyA(buf, "kiwi");
8406     r = MsiRecordGetString(rec, 1, buf, &sz);
8407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8408     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8409
8410     sz = MAX_PATH;
8411     lstrcpyA(buf, "kiwi");
8412     r = MsiRecordGetString(rec, 2, buf, &sz);
8413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8414     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8415
8416     sz = MAX_PATH;
8417     lstrcpyA(buf, "kiwi");
8418     r = MsiRecordGetString(rec, 3, buf, &sz);
8419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8420     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8421
8422     sz = MAX_PATH;
8423     lstrcpyA(buf, "kiwi");
8424     r = MsiRecordGetString(rec, 4, buf, &sz);
8425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8426     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8427
8428     sz = MAX_PATH;
8429     lstrcpyA(buf, "kiwi");
8430     r = MsiRecordGetString(rec, 5, buf, &sz);
8431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8432     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8433
8434     MsiCloseHandle(rec);
8435
8436     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8438
8439     sz = MAX_PATH;
8440     lstrcpyA(buf, "kiwi");
8441     r = MsiRecordGetString(rec, 1, buf, &sz);
8442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8443     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8444
8445     sz = MAX_PATH;
8446     lstrcpyA(buf, "kiwi");
8447     r = MsiRecordGetString(rec, 2, buf, &sz);
8448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8449     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8450
8451     sz = MAX_PATH;
8452     lstrcpyA(buf, "kiwi");
8453     r = MsiRecordGetString(rec, 3, buf, &sz);
8454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8455     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8456
8457     sz = MAX_PATH;
8458     lstrcpyA(buf, "kiwi");
8459     r = MsiRecordGetString(rec, 4, buf, &sz);
8460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8461     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8462
8463     sz = MAX_PATH;
8464     lstrcpyA(buf, "kiwi");
8465     r = MsiRecordGetString(rec, 5, buf, &sz);
8466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8467     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8468
8469     MsiCloseHandle(rec);
8470     MsiViewClose(view);
8471     MsiCloseHandle(view);
8472
8473     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8474             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8475     r = run_query(hdb, 0, query);
8476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8477
8478     query = "SELECT * FROM `T`";
8479     r = do_query(hdb, query, &rec);
8480
8481     sz = MAX_PATH;
8482     lstrcpyA(buf, "kiwi");
8483     r = MsiRecordGetString(rec, 1, buf, &sz);
8484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8485     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8486
8487     r = MsiRecordGetInteger(rec, 2);
8488     ok(r == 3, "Expected 3, got %d\n", r);
8489
8490     sz = MAX_PATH;
8491     lstrcpyA(buf, "kiwi");
8492     r = MsiRecordGetString(rec, 3, buf, &sz);
8493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8494     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8495
8496     r = MsiRecordGetInteger(rec, 4);
8497     ok(r == 2, "Expected 2, got %d\n", r);
8498
8499     r = MsiRecordGetInteger(rec, 5);
8500     ok(r == 1, "Expected 1, got %d\n", r);
8501
8502     MsiCloseHandle(rec);
8503
8504     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8505     r = MsiDatabaseOpenView(hdb, query, &view);
8506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8507     r = MsiViewExecute(view, 0);
8508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8509
8510     r = MsiViewFetch(view, &rec);
8511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8512
8513     sz = MAX_PATH;
8514     lstrcpyA(buf, "kiwi");
8515     r = MsiRecordGetString(rec, 1, buf, &sz);
8516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8517     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8518
8519     r = MsiRecordGetInteger(rec, 2);
8520     ok(r == 1, "Expected 1, got %d\n", r);
8521
8522     sz = MAX_PATH;
8523     lstrcpyA(buf, "kiwi");
8524     r = MsiRecordGetString(rec, 3, buf, &sz);
8525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8526     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8527
8528     MsiCloseHandle(rec);
8529
8530     r = MsiViewFetch(view, &rec);
8531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8532
8533     sz = MAX_PATH;
8534     lstrcpyA(buf, "kiwi");
8535     r = MsiRecordGetString(rec, 1, buf, &sz);
8536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8537     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8538
8539     r = MsiRecordGetInteger(rec, 2);
8540     ok(r == 2, "Expected 2, got %d\n", r);
8541
8542     sz = MAX_PATH;
8543     lstrcpyA(buf, "kiwi");
8544     r = MsiRecordGetString(rec, 3, buf, &sz);
8545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8546     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8547
8548     MsiCloseHandle(rec);
8549
8550     r = MsiViewFetch(view, &rec);
8551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8552
8553     sz = MAX_PATH;
8554     lstrcpyA(buf, "kiwi");
8555     r = MsiRecordGetString(rec, 1, buf, &sz);
8556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8557     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8558
8559     r = MsiRecordGetInteger(rec, 2);
8560     ok(r == 3, "Expected 3, got %d\n", r);
8561
8562     sz = MAX_PATH;
8563     lstrcpyA(buf, "kiwi");
8564     r = MsiRecordGetString(rec, 3, buf, &sz);
8565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8566     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8567
8568     MsiCloseHandle(rec);
8569
8570     r = MsiViewFetch(view, &rec);
8571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8572
8573     sz = MAX_PATH;
8574     lstrcpyA(buf, "kiwi");
8575     r = MsiRecordGetString(rec, 1, buf, &sz);
8576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8577     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8578
8579     r = MsiRecordGetInteger(rec, 2);
8580     ok(r == 4, "Expected 4, got %d\n", r);
8581
8582     sz = MAX_PATH;
8583     lstrcpyA(buf, "kiwi");
8584     r = MsiRecordGetString(rec, 3, buf, &sz);
8585     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8586     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8587
8588     MsiCloseHandle(rec);
8589
8590     r = MsiViewFetch(view, &rec);
8591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8592
8593     sz = MAX_PATH;
8594     lstrcpyA(buf, "kiwi");
8595     r = MsiRecordGetString(rec, 1, buf, &sz);
8596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8597     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8598
8599     r = MsiRecordGetInteger(rec, 2);
8600     ok(r == 5, "Expected 5, got %d\n", r);
8601
8602     sz = MAX_PATH;
8603     lstrcpyA(buf, "kiwi");
8604     r = MsiRecordGetString(rec, 3, buf, &sz);
8605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8606     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8607
8608     MsiCloseHandle(rec);
8609
8610     r = MsiViewFetch(view, &rec);
8611     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8612
8613     MsiViewClose(view);
8614     MsiCloseHandle(view);
8615
8616     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8617             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8618             "PRIMARY KEY `C`, `A`, `D`)";
8619     r = run_query(hdb, 0, query);
8620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8621
8622     query = "SELECT * FROM `Z`";
8623     r = MsiDatabaseOpenView(hdb, query, &view);
8624     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8625
8626     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8628
8629     sz = MAX_PATH;
8630     lstrcpyA(buf, "kiwi");
8631     r = MsiRecordGetString(rec, 1, buf, &sz);
8632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8633     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8634
8635     sz = MAX_PATH;
8636     lstrcpyA(buf, "kiwi");
8637     r = MsiRecordGetString(rec, 2, buf, &sz);
8638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8639     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8640
8641     sz = MAX_PATH;
8642     lstrcpyA(buf, "kiwi");
8643     r = MsiRecordGetString(rec, 3, buf, &sz);
8644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8645     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8646
8647     sz = MAX_PATH;
8648     lstrcpyA(buf, "kiwi");
8649     r = MsiRecordGetString(rec, 4, buf, &sz);
8650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8651     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8652
8653     sz = MAX_PATH;
8654     lstrcpyA(buf, "kiwi");
8655     r = MsiRecordGetString(rec, 5, buf, &sz);
8656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8657     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8658
8659     MsiCloseHandle(rec);
8660
8661     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8663
8664     sz = MAX_PATH;
8665     lstrcpyA(buf, "kiwi");
8666     r = MsiRecordGetString(rec, 1, buf, &sz);
8667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8668     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8669
8670     sz = MAX_PATH;
8671     lstrcpyA(buf, "kiwi");
8672     r = MsiRecordGetString(rec, 2, buf, &sz);
8673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8674     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8675
8676     sz = MAX_PATH;
8677     lstrcpyA(buf, "kiwi");
8678     r = MsiRecordGetString(rec, 3, buf, &sz);
8679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8680     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8681
8682     sz = MAX_PATH;
8683     lstrcpyA(buf, "kiwi");
8684     r = MsiRecordGetString(rec, 4, buf, &sz);
8685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8686     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8687
8688     sz = MAX_PATH;
8689     lstrcpyA(buf, "kiwi");
8690     r = MsiRecordGetString(rec, 5, buf, &sz);
8691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8692     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8693
8694     MsiCloseHandle(rec);
8695     MsiViewClose(view);
8696     MsiCloseHandle(view);
8697
8698     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
8699             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8700     r = run_query(hdb, 0, query);
8701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8702
8703     query = "SELECT * FROM `Z`";
8704     r = do_query(hdb, query, &rec);
8705
8706     r = MsiRecordGetInteger(rec, 1);
8707     ok(r == 2, "Expected 2, got %d\n", r);
8708
8709     sz = MAX_PATH;
8710     lstrcpyA(buf, "kiwi");
8711     r = MsiRecordGetString(rec, 2, buf, &sz);
8712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8713     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8714
8715     sz = MAX_PATH;
8716     lstrcpyA(buf, "kiwi");
8717     r = MsiRecordGetString(rec, 3, buf, &sz);
8718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8719     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8720
8721     r = MsiRecordGetInteger(rec, 4);
8722     ok(r == 3, "Expected 3, got %d\n", r);
8723
8724     r = MsiRecordGetInteger(rec, 5);
8725     ok(r == 1, "Expected 1, got %d\n", r);
8726
8727     MsiCloseHandle(rec);
8728
8729     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8730     r = MsiDatabaseOpenView(hdb, query, &view);
8731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8732     r = MsiViewExecute(view, 0);
8733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8734
8735     r = MsiViewFetch(view, &rec);
8736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8737
8738     sz = MAX_PATH;
8739     lstrcpyA(buf, "kiwi");
8740     r = MsiRecordGetString(rec, 1, buf, &sz);
8741     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8742     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8743
8744     r = MsiRecordGetInteger(rec, 2);
8745     ok(r == 1, "Expected 1, got %d\n", r);
8746
8747     sz = MAX_PATH;
8748     lstrcpyA(buf, "kiwi");
8749     r = MsiRecordGetString(rec, 3, buf, &sz);
8750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8751     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8752
8753     MsiCloseHandle(rec);
8754
8755     r = MsiViewFetch(view, &rec);
8756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8757
8758     sz = MAX_PATH;
8759     lstrcpyA(buf, "kiwi");
8760     r = MsiRecordGetString(rec, 1, buf, &sz);
8761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8762     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8763
8764     r = MsiRecordGetInteger(rec, 2);
8765     ok(r == 2, "Expected 2, got %d\n", r);
8766
8767     sz = MAX_PATH;
8768     lstrcpyA(buf, "kiwi");
8769     r = MsiRecordGetString(rec, 3, buf, &sz);
8770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8771     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8772
8773     MsiCloseHandle(rec);
8774
8775     r = MsiViewFetch(view, &rec);
8776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8777
8778     sz = MAX_PATH;
8779     lstrcpyA(buf, "kiwi");
8780     r = MsiRecordGetString(rec, 1, buf, &sz);
8781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8782     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8783
8784     r = MsiRecordGetInteger(rec, 2);
8785     ok(r == 3, "Expected 3, got %d\n", r);
8786
8787     sz = MAX_PATH;
8788     lstrcpyA(buf, "kiwi");
8789     r = MsiRecordGetString(rec, 3, buf, &sz);
8790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8791     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8792
8793     MsiCloseHandle(rec);
8794
8795     r = MsiViewFetch(view, &rec);
8796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8797
8798     sz = MAX_PATH;
8799     lstrcpyA(buf, "kiwi");
8800     r = MsiRecordGetString(rec, 1, buf, &sz);
8801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8802     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8803
8804     r = MsiRecordGetInteger(rec, 2);
8805     ok(r == 4, "Expected 4, got %d\n", r);
8806
8807     sz = MAX_PATH;
8808     lstrcpyA(buf, "kiwi");
8809     r = MsiRecordGetString(rec, 3, buf, &sz);
8810     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8811     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8812
8813     MsiCloseHandle(rec);
8814
8815     r = MsiViewFetch(view, &rec);
8816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8817
8818     sz = MAX_PATH;
8819     lstrcpyA(buf, "kiwi");
8820     r = MsiRecordGetString(rec, 1, buf, &sz);
8821     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8822     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8823
8824     r = MsiRecordGetInteger(rec, 2);
8825     ok(r == 5, "Expected 5, got %d\n", r);
8826
8827     sz = MAX_PATH;
8828     lstrcpyA(buf, "kiwi");
8829     r = MsiRecordGetString(rec, 3, buf, &sz);
8830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8831     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8832
8833     MsiCloseHandle(rec);
8834
8835     r = MsiViewFetch(view, &rec);
8836     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8837
8838     MsiViewClose(view);
8839     MsiCloseHandle(view);
8840
8841     MsiCloseHandle(hdb);
8842     DeleteFileA(msifile);
8843 }
8844
8845 START_TEST(db)
8846 {
8847     test_msidatabase();
8848     test_msiinsert();
8849     test_msidecomposedesc();
8850     test_msibadqueries();
8851     test_viewmodify();
8852     test_viewgetcolumninfo();
8853     test_getcolinfo();
8854     test_msiexport();
8855     test_longstrings();
8856     test_streamtable();
8857     test_binary();
8858     test_where_not_in_selected();
8859     test_where();
8860     test_msiimport();
8861     test_binary_import();
8862     test_markers();
8863     test_handle_limit();
8864     test_try_transform();
8865     test_join();
8866     test_temporary_table();
8867     test_alter();
8868     test_integers();
8869     test_update();
8870     test_special_tables();
8871     test_tables_order();
8872     test_rows_order();
8873     test_select_markers();
8874     test_viewmodify_update();
8875     test_viewmodify_assign();
8876     test_stringtable();
8877     test_viewmodify_delete();
8878     test_defaultdatabase();
8879     test_order();
8880     test_viewmodify_delete_temporary();
8881     test_deleterow();
8882     test_quotes();
8883     test_carriagereturn();
8884     test_noquotes();
8885     test_forcecodepage();
8886     test_viewmodify_refresh();
8887     test_where_viewmodify();
8888     test_storages_table();
8889     test_dbtopackage();
8890     test_droptable();
8891     test_dbmerge();
8892     test_select_with_tablenames();
8893     test_insertorder();
8894     test_columnorder();
8895     test_suminfo_import();
8896 }