msi/tests: Use only uppercase characters for the PID_REVNUMBER property.
[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 = MsiDatabaseCommit( hdb );
100     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
101
102     res = MsiCloseHandle( hdb );
103     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
104
105     res = MsiOpenDatabase( msifile, MSIDBOPEN_DIRECT, &hdb );
106     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
107
108     res = MsiCloseHandle( hdb );
109     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
110
111     res = MsiOpenDatabase( msifile, MSIDBOPEN_TRANSACT, &hdb );
112     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
113
114     res = MsiCloseHandle( hdb );
115     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
116     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
117
118     /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
119     res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
120     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
121
122     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
123
124     res = MsiCloseHandle( hdb );
125     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
126
127     ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile ), "database should exist\n");
128
129     res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
130     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
131
132     res = MsiDatabaseCommit( hdb );
133     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
134
135     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
136
137     res = MsiCloseHandle( hdb );
138     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
139
140     res = DeleteFile( msifile2 );
141     ok( res == TRUE, "Failed to delete database\n" );
142
143     res = DeleteFile( msifile );
144     ok( res == TRUE, "Failed to delete database\n" );
145 }
146
147 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
148 {
149     MSIHANDLE hview = 0;
150     UINT r, ret;
151
152     if (phrec)
153         *phrec = 0;
154
155     /* open a select query */
156     r = MsiDatabaseOpenView(hdb, query, &hview);
157     if (r != ERROR_SUCCESS)
158         return r;
159     r = MsiViewExecute(hview, 0);
160     if (r != ERROR_SUCCESS)
161         return r;
162     ret = MsiViewFetch(hview, phrec);
163     r = MsiViewClose(hview);
164     if (r != ERROR_SUCCESS)
165         return r;
166     r = MsiCloseHandle(hview);
167     if (r != ERROR_SUCCESS)
168         return r;
169     return ret;
170 }
171
172 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
173 {
174     MSIHANDLE hview = 0;
175     UINT r;
176
177     r = MsiDatabaseOpenView(hdb, query, &hview);
178     if( r != ERROR_SUCCESS )
179         return r;
180
181     r = MsiViewExecute(hview, hrec);
182     if( r == ERROR_SUCCESS )
183         r = MsiViewClose(hview);
184     MsiCloseHandle(hview);
185     return r;
186 }
187
188 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
189 {
190     MSIHANDLE hview = 0;
191     UINT r;
192
193     r = MsiDatabaseOpenViewW(hdb, query, &hview);
194     if( r != ERROR_SUCCESS )
195         return r;
196
197     r = MsiViewExecute(hview, hrec);
198     if( r == ERROR_SUCCESS )
199         r = MsiViewClose(hview);
200     MsiCloseHandle(hview);
201     return r;
202 }
203
204 static UINT create_component_table( MSIHANDLE hdb )
205 {
206     return run_query( hdb, 0,
207             "CREATE TABLE `Component` ( "
208             "`Component` CHAR(72) NOT NULL, "
209             "`ComponentId` CHAR(38), "
210             "`Directory_` CHAR(72) NOT NULL, "
211             "`Attributes` SHORT NOT NULL, "
212             "`Condition` CHAR(255), "
213             "`KeyPath` CHAR(72) "
214             "PRIMARY KEY `Component`)" );
215 }
216
217 static UINT create_custom_action_table( MSIHANDLE hdb )
218 {
219     return run_query( hdb, 0,
220             "CREATE TABLE `CustomAction` ( "
221             "`Action` CHAR(72) NOT NULL, "
222             "`Type` SHORT NOT NULL, "
223             "`Source` CHAR(72), "
224             "`Target` CHAR(255) "
225             "PRIMARY KEY `Action`)" );
226 }
227
228 static UINT create_directory_table( MSIHANDLE hdb )
229 {
230     return run_query( hdb, 0,
231             "CREATE TABLE `Directory` ( "
232             "`Directory` CHAR(255) NOT NULL, "
233             "`Directory_Parent` CHAR(255), "
234             "`DefaultDir` CHAR(255) NOT NULL "
235             "PRIMARY KEY `Directory`)" );
236 }
237
238 static UINT create_feature_components_table( MSIHANDLE hdb )
239 {
240     return run_query( hdb, 0,
241             "CREATE TABLE `FeatureComponents` ( "
242             "`Feature_` CHAR(38) NOT NULL, "
243             "`Component_` CHAR(72) NOT NULL "
244             "PRIMARY KEY `Feature_`, `Component_` )" );
245 }
246
247 static UINT create_std_dlls_table( MSIHANDLE hdb )
248 {
249     return run_query( hdb, 0,
250             "CREATE TABLE `StdDlls` ( "
251             "`File` CHAR(255) NOT NULL, "
252             "`Binary_` CHAR(72) NOT NULL "
253             "PRIMARY KEY `File` )" );
254 }
255
256 static UINT create_binary_table( MSIHANDLE hdb )
257 {
258     return run_query( hdb, 0,
259             "CREATE TABLE `Binary` ( "
260             "`Name` CHAR(72) NOT NULL, "
261             "`Data` CHAR(72) NOT NULL "
262             "PRIMARY KEY `Name` )" );
263 }
264
265 #define make_add_entry(type, qtext) \
266     static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
267     { \
268         char insert[] = qtext; \
269         char *query; \
270         UINT sz, r; \
271         sz = strlen(values) + sizeof insert; \
272         query = HeapAlloc(GetProcessHeap(),0,sz); \
273         sprintf(query,insert,values); \
274         r = run_query( hdb, 0, query ); \
275         HeapFree(GetProcessHeap(), 0, query); \
276         return r; \
277     }
278
279 make_add_entry(component,
280                "INSERT INTO `Component`  "
281                "(`Component`, `ComponentId`, `Directory_`, "
282                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
283
284 make_add_entry(custom_action,
285                "INSERT INTO `CustomAction`  "
286                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
287
288 make_add_entry(feature_components,
289                "INSERT INTO `FeatureComponents` "
290                "(`Feature_`, `Component_`) VALUES( %s )")
291
292 make_add_entry(std_dlls,
293                "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
294
295 make_add_entry(binary,
296                "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
297
298 static void test_msiinsert(void)
299 {
300     MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0;
301     UINT r;
302     const char *query;
303     char buf[80];
304     DWORD sz;
305
306     DeleteFile(msifile);
307
308     /* just MsiOpenDatabase should not create a file */
309     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
310     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
311
312     /* create a table */
313     query = "CREATE TABLE `phone` ( "
314             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
315             "PRIMARY KEY `id`)";
316     r = MsiDatabaseOpenView(hdb, query, &hview);
317     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
318     r = MsiViewExecute(hview, 0);
319     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
320     r = MsiViewClose(hview);
321     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
322     r = MsiCloseHandle(hview);
323     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
324
325     query = "SELECT * FROM phone WHERE number = '8675309'";
326     r = MsiDatabaseOpenView(hdb, query, &hview2);
327     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
328     r = MsiViewExecute(hview2, 0);
329     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
330     r = MsiViewFetch(hview2, &hrec);
331     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
332
333     /* insert a value into it */
334     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
335         "VALUES('1', 'Abe', '8675309')";
336     r = MsiDatabaseOpenView(hdb, query, &hview);
337     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
338     r = MsiViewExecute(hview, 0);
339     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
340     r = MsiViewClose(hview);
341     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
342     r = MsiCloseHandle(hview);
343     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
344
345     r = MsiViewFetch(hview2, &hrec);
346     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
347     r = MsiViewExecute(hview2, 0);
348     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
349     r = MsiViewFetch(hview2, &hrec);
350     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r);
351
352     r = MsiCloseHandle(hrec);
353     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
354     r = MsiViewClose(hview2);
355     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
356     r = MsiCloseHandle(hview2);
357     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
358
359     query = "SELECT * FROM `phone` WHERE `id` = 1";
360     r = do_query(hdb, query, &hrec);
361     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
362
363     /* check the record contains what we put in it */
364     r = MsiRecordGetFieldCount(hrec);
365     ok(r == 3, "record count wrong\n");
366
367     r = MsiRecordIsNull(hrec, 0);
368     ok(r == FALSE, "field 0 not null\n");
369
370     r = MsiRecordGetInteger(hrec, 1);
371     ok(r == 1, "field 1 contents wrong\n");
372     sz = sizeof buf;
373     r = MsiRecordGetString(hrec, 2, buf, &sz);
374     ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
375     ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
376     sz = sizeof buf;
377     r = MsiRecordGetString(hrec, 3, buf, &sz);
378     ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
379     ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
380
381     r = MsiCloseHandle(hrec);
382     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
383
384     /* open a select query */
385     hrec = 100;
386     query = "SELECT * FROM `phone` WHERE `id` >= 10";
387     r = do_query(hdb, query, &hrec);
388     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
389     ok(hrec == 0, "hrec should be null\n");
390
391     r = MsiCloseHandle(hrec);
392     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
393
394     query = "SELECT * FROM `phone` WHERE `id` < 0";
395     r = do_query(hdb, query, &hrec);
396     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
397
398     query = "SELECT * FROM `phone` WHERE `id` <= 0";
399     r = do_query(hdb, query, &hrec);
400     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
401
402     query = "SELECT * FROM `phone` WHERE `id` <> 1";
403     r = do_query(hdb, query, &hrec);
404     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
405
406     query = "SELECT * FROM `phone` WHERE `id` > 10";
407     r = do_query(hdb, query, &hrec);
408     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
409
410     /* now try a few bad INSERT xqueries */
411     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
412         "VALUES(?, ?)";
413     r = MsiDatabaseOpenView(hdb, query, &hview);
414     ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
415
416     /* construct a record to insert */
417     hrec = MsiCreateRecord(4);
418     r = MsiRecordSetInteger(hrec, 1, 2);
419     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
420     r = MsiRecordSetString(hrec, 2, "Adam");
421     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
422     r = MsiRecordSetString(hrec, 3, "96905305");
423     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
424
425     /* insert another value, using a record and wildcards */
426     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
427         "VALUES(?, ?, ?)";
428     r = MsiDatabaseOpenView(hdb, query, &hview);
429     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
430
431     if (r == ERROR_SUCCESS)
432     {
433         r = MsiViewExecute(hview, hrec);
434         ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
435         r = MsiViewClose(hview);
436         ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
437         r = MsiCloseHandle(hview);
438         ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
439     }
440     r = MsiCloseHandle(hrec);
441     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
442
443     r = MsiViewFetch(0, NULL);
444     ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
445
446     r = MsiDatabaseCommit(hdb);
447     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
448
449     r = MsiCloseHandle(hdb);
450     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
451
452     r = DeleteFile(msifile);
453     ok(r == TRUE, "file didn't exist after commit\n");
454 }
455
456 typedef UINT (WINAPI *fnMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
457 static fnMsiDecomposeDescriptorA pMsiDecomposeDescriptorA;
458
459 static void test_msidecomposedesc(void)
460 {
461     char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
462     const char *desc;
463     UINT r;
464     DWORD len;
465     HMODULE hmod;
466
467     hmod = GetModuleHandle("msi.dll");
468     pMsiDecomposeDescriptorA = (fnMsiDecomposeDescriptorA)
469         GetProcAddress(hmod, "MsiDecomposeDescriptorA");
470     if (!pMsiDecomposeDescriptorA)
471         return;
472
473     /* test a valid feature descriptor */
474     desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
475     len = 0;
476     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
477     ok(r == ERROR_SUCCESS, "returned an error\n");
478     ok(len == strlen(desc), "length was wrong\n");
479     ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
480     ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
481     ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
482
483     /* test an invalid feature descriptor with too many characters */
484     desc = "']gAVn-}f(ZXfeAR6.ji"
485            "ThisWillFailIfTheresMoreThanAGuidsChars>"
486            "3w2x^IGfe?CxI5heAvk.";
487     len = 0;
488     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
489     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
490
491     /*
492      * Test a valid feature descriptor with the
493      * maximum number of characters and some trailing characters.
494      */
495     desc = "']gAVn-}f(ZXfeAR6.ji"
496            "ThisWillWorkIfTheresLTEThanAGuidsChars>"
497            "3w2x^IGfe?CxI5heAvk."
498            "extra";
499     len = 0;
500     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
501     ok(r == ERROR_SUCCESS, "returned wrong error\n");
502     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
503
504     len = 0;
505     r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
506     ok(r == ERROR_SUCCESS, "returned wrong error\n");
507     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
508
509     len = 0;
510     r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
511     ok(r == ERROR_SUCCESS, "returned wrong error\n");
512     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
513
514     len = 0;
515     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
516     ok(r == ERROR_SUCCESS, "returned wrong error\n");
517     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
518
519     len = 0;
520     r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
521     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
522     ok(len == 0, "length wrong\n");
523
524     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL);
525     ok(r == ERROR_SUCCESS, "returned wrong error\n");
526 }
527
528 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
529 {
530     MSIHANDLE htab = 0;
531     UINT res;
532
533     res = MsiDatabaseOpenView( hdb, szQuery, &htab );
534     if(res == ERROR_SUCCESS )
535     {
536         UINT r;
537
538         r = MsiViewExecute( htab, hrec );
539         if(r != ERROR_SUCCESS )
540             res = r;
541
542         r = MsiViewClose( htab );
543         if(r != ERROR_SUCCESS )
544             res = r;
545
546         r = MsiCloseHandle( htab );
547         if(r != ERROR_SUCCESS )
548             res = r;
549     }
550     return res;
551 }
552
553 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
554 {
555     return try_query_param( hdb, szQuery, 0 );
556 }
557
558 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
559 {
560     MSIHANDLE hrec = 0;
561     UINT r;
562
563     hrec = MsiCreateRecord( 1 );
564     MsiRecordSetString( hrec, 1, "Hello");
565
566     r = try_query_param( hdb, szQuery, hrec );
567
568     MsiCloseHandle( hrec );
569     return r;
570 }
571
572 static void test_msibadqueries(void)
573 {
574     MSIHANDLE hdb = 0;
575     UINT r;
576
577     DeleteFile(msifile);
578
579     /* just MsiOpenDatabase should not create a file */
580     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
581     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
582
583     r = MsiDatabaseCommit( hdb );
584     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
585
586     r = MsiCloseHandle( hdb );
587     ok(r == ERROR_SUCCESS , "Failed to close database\n");
588
589     /* open it readonly */
590     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb );
591     ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
592
593     /* add a table to it */
594     r = try_query( hdb, "select * from _Tables");
595     ok(r == ERROR_SUCCESS , "query 1 failed\n");
596
597     r = MsiCloseHandle( hdb );
598     ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
599
600     /* open it read/write */
601     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
602     ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
603
604     /* a bunch of test queries that fail with the native MSI */
605
606     r = try_query( hdb, "CREATE TABLE");
607     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
608
609     r = try_query( hdb, "CREATE TABLE `a`");
610     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
611
612     r = try_query( hdb, "CREATE TABLE `a` ()");
613     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
614
615     r = try_query( hdb, "CREATE TABLE `a` (`b`)");
616     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
617
618     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
619     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
620
621     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
622     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
623
624     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
625     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
626
627     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
628     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
629
630     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
631     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
632
633     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
634     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
635
636     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
637     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
638
639     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
640     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
641
642     r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
643     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
644
645     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
646     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
647
648     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
649     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
650
651     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
652     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
653
654     r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
655     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
656
657     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
658     ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
659
660     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
661     ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
662
663     r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
664           "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
665     ok(r == ERROR_SUCCESS , "query 4 failed\n");
666
667     r = MsiDatabaseCommit( hdb );
668     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
669
670     r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
671                           "PRIMARY KEY `foo`)");
672     ok(r == ERROR_SUCCESS , "query 4 failed\n");
673
674     r = try_insert_query( hdb, "insert into a  ( `b` ) VALUES ( ? )");
675     ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
676
677     r = MsiDatabaseCommit( hdb );
678     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
679
680     r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
681                           "PRIMARY KEY `ba`)");
682     ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
683
684     r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
685     ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
686
687     r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
688                           "PRIMARY KEY `t`)");
689     ok(r == ERROR_SUCCESS , "query 7 failed\n");
690
691     r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
692     ok(r == ERROR_SUCCESS , "query 8 failed\n");
693
694     r = try_query( hdb, "select * from c");
695     ok(r == ERROR_SUCCESS , "query failed\n");
696
697     r = try_query( hdb, "select * from c where b = 'x");
698     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
699
700     r = try_query( hdb, "select * from c where b = 'x'");
701     ok(r == ERROR_SUCCESS, "query failed\n");
702
703     r = try_query( hdb, "select * from 'c'");
704     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
705
706     r = try_query( hdb, "select * from ''");
707     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
708
709     r = try_query( hdb, "select * from c where b = x");
710     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
711
712     r = try_query( hdb, "select * from c where b = \"x\"");
713     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
714
715     r = try_query( hdb, "select * from c where b = 'x'");
716     ok(r == ERROR_SUCCESS, "query failed\n");
717
718     r = try_query( hdb, "select * from c where b = '\"x'");
719     ok(r == ERROR_SUCCESS, "query failed\n");
720
721     if (0)  /* FIXME: this query causes trouble with other tests */
722     {
723         r = try_query( hdb, "select * from c where b = '\\\'x'");
724         ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
725     }
726
727     r = try_query( hdb, "select * from 'c'");
728     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
729
730     r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`");
731     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
732
733     r = try_query( hdb, "select `c`.b` from `c`");
734     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
735
736     r = try_query( hdb, "select `c`.`b from `c`");
737     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
738
739     r = try_query( hdb, "select `c`.b from `c`");
740     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
741
742     r = try_query( hdb, "select `c.`b` from `c`");
743     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
744
745     r = try_query( hdb, "select c`.`b` from `c`");
746     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
747
748     r = try_query( hdb, "select c.`b` from `c`");
749     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
750
751     r = try_query( hdb, "select `c`.`b` from c`");
752     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
753
754     r = try_query( hdb, "select `c`.`b` from `c");
755     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
756
757     r = try_query( hdb, "select `c`.`b` from c");
758     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
759
760     r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
761     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
762
763     r = try_query( hdb, "SELECT * FROM \5a" );
764     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
765
766     r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
767     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
768
769     r = try_query( hdb, "SELECT * FROM a\5" );
770     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
771
772     r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
773     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
774
775     r = try_query( hdb, "SELECT * FROM -a" );
776     todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
777
778     r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
779     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
780
781     r = try_query( hdb, "SELECT * FROM a-" );
782     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
783
784     r = MsiCloseHandle( hdb );
785     ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
786
787     r = DeleteFile( msifile );
788     ok(r == TRUE, "file didn't exist after commit\n");
789 }
790
791 static void test_viewmodify(void)
792 {
793     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
794     UINT r;
795     MSIDBERROR err;
796     const char *query;
797     char buffer[0x100];
798     DWORD sz;
799
800     DeleteFile(msifile);
801
802     /* just MsiOpenDatabase should not create a file */
803     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
804     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
805
806     query = "CREATE TABLE `phone` ( "
807             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
808             "PRIMARY KEY `id`)";
809     r = run_query( hdb, 0, query );
810     ok(r == ERROR_SUCCESS, "query failed\n");
811
812     query = "CREATE TABLE `_Validation` ( "
813             "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
814             "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
815             "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
816             "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)";
817     r = run_query( hdb, 0, query );
818     ok(r == ERROR_SUCCESS, "query failed\n");
819
820     query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) "
821             "VALUES('phone', 'id', 'N')";
822     r = run_query( hdb, 0, query );
823     ok(r == ERROR_SUCCESS, "query failed\n");
824
825     /* check what the error function reports without doing anything */
826     sz = 0;
827     /* passing NULL as the 3rd param make function to crash on older platforms */
828     err = MsiViewGetError( 0, NULL, &sz );
829     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
830
831     /* open a view */
832     query = "SELECT * FROM `phone`";
833     r = MsiDatabaseOpenView(hdb, query, &hview);
834     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
835
836     /* see what happens with a good hview and bad args */
837     err = MsiViewGetError( hview, NULL, NULL );
838     ok(err == MSIDBERROR_INVALIDARG || err == MSIDBERROR_NOERROR,
839        "MsiViewGetError returns %u (expected -3)\n", err);
840     err = MsiViewGetError( hview, buffer, NULL );
841     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
842
843     /* see what happens with a zero length buffer */
844     sz = 0;
845     buffer[0] = 'x';
846     err = MsiViewGetError( hview, buffer, &sz );
847     ok(err == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
848     ok(buffer[0] == 'x', "buffer cleared\n");
849     ok(sz == 0, "size not zero\n");
850
851     /* ok this one is strange */
852     sz = 0;
853     err = MsiViewGetError( hview, NULL, &sz );
854     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
855     ok(sz == 0, "size not zero\n");
856
857     /* see if it really has an error */
858     sz = sizeof buffer;
859     buffer[0] = 'x';
860     err = MsiViewGetError( hview, buffer, &sz );
861     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
862     ok(buffer[0] == 0, "buffer not cleared\n");
863     ok(sz == 0, "size not zero\n");
864
865     r = MsiViewExecute(hview, 0);
866     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
867
868     /* try some invalid records */
869     r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
870     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
871     r = MsiViewModify(hview, -1, 0 );
872     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
873
874     /* try an small record */
875     hrec = MsiCreateRecord(1);
876     r = MsiViewModify(hview, -1, hrec );
877     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
878
879     sz = sizeof buffer;
880     buffer[0] = 'x';
881     err = MsiViewGetError( hview, buffer, &sz );
882     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
883     ok(buffer[0] == 0, "buffer not cleared\n");
884     ok(sz == 0, "size not zero\n");
885
886     r = MsiCloseHandle(hrec);
887     ok(r == ERROR_SUCCESS, "failed to close record\n");
888
889     /* insert a valid record */
890     hrec = MsiCreateRecord(3);
891
892     r = MsiRecordSetInteger(hrec, 1, 1);
893     ok(r == ERROR_SUCCESS, "failed to set integer\n");
894     r = MsiRecordSetString(hrec, 2, "bob");
895     ok(r == ERROR_SUCCESS, "failed to set string\n");
896     r = MsiRecordSetString(hrec, 3, "7654321");
897     ok(r == ERROR_SUCCESS, "failed to set string\n");
898
899     r = MsiViewExecute(hview, 0);
900     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
901     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
902     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
903
904     /* validate it */
905     r = MsiViewExecute(hview, 0);
906     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
907
908     r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec );
909     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r);
910
911     sz = sizeof buffer;
912     buffer[0] = 'x';
913     err = MsiViewGetError( hview, buffer, &sz );
914     ok(err == MSIDBERROR_DUPLICATEKEY, "MsiViewGetError returned %u\n", err);
915     ok(!strcmp(buffer, "id"), "expected \"id\" c, got \"%s\"\n", buffer);
916     ok(sz == 2, "size not 2\n");
917
918     /* insert the same thing again */
919     r = MsiViewExecute(hview, 0);
920     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
921
922     /* should fail ... */
923     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
924     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
925
926     /* try to merge the same record */
927     r = MsiViewExecute(hview, 0);
928     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
929     r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
930     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
931
932     r = MsiCloseHandle(hrec);
933     ok(r == ERROR_SUCCESS, "failed to close record\n");
934
935     /* try merging a new record */
936     hrec = MsiCreateRecord(3);
937
938     r = MsiRecordSetInteger(hrec, 1, 10);
939     ok(r == ERROR_SUCCESS, "failed to set integer\n");
940     r = MsiRecordSetString(hrec, 2, "pepe");
941     ok(r == ERROR_SUCCESS, "failed to set string\n");
942     r = MsiRecordSetString(hrec, 3, "7654321");
943     ok(r == ERROR_SUCCESS, "failed to set string\n");
944
945     r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
946     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
947     r = MsiViewExecute(hview, 0);
948     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
949
950     r = MsiCloseHandle(hrec);
951     ok(r == ERROR_SUCCESS, "failed to close record\n");
952
953     r = MsiViewClose(hview);
954     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
955     r = MsiCloseHandle(hview);
956     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
957
958     query = "SELECT * FROM `phone`";
959     r = MsiDatabaseOpenView(hdb, query, &hview);
960     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
961
962     r = MsiViewExecute(hview, 0);
963     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
964
965     r = MsiViewFetch(hview, &hrec);
966     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
967
968     r = MsiRecordGetInteger(hrec, 1);
969     ok(r == 1, "Expected 1, got %d\n", r);
970
971     sz = sizeof(buffer);
972     r = MsiRecordGetString(hrec, 2, buffer, &sz);
973     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
974     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
975
976     sz = sizeof(buffer);
977     r = MsiRecordGetString(hrec, 3, buffer, &sz);
978     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
979     ok(!lstrcmp(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
980
981     /* update the view, non-primary key */
982     r = MsiRecordSetString(hrec, 3, "3141592");
983     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
984
985     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
986     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
987
988     /* do it again */
989     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
990     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
991
992     /* update the view, primary key */
993     r = MsiRecordSetInteger(hrec, 1, 5);
994     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
995
996     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
997     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
998
999     r = MsiCloseHandle(hrec);
1000     ok(r == ERROR_SUCCESS, "failed to close record\n");
1001
1002     r = MsiViewClose(hview);
1003     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1004     r = MsiCloseHandle(hview);
1005     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1006
1007     query = "SELECT * FROM `phone`";
1008     r = MsiDatabaseOpenView(hdb, query, &hview);
1009     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1010
1011     r = MsiViewExecute(hview, 0);
1012     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1013
1014     r = MsiViewFetch(hview, &hrec);
1015     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1016
1017     r = MsiRecordGetInteger(hrec, 1);
1018     ok(r == 1, "Expected 1, got %d\n", r);
1019
1020     sz = sizeof(buffer);
1021     r = MsiRecordGetString(hrec, 2, buffer, &sz);
1022     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1023     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
1024
1025     sz = sizeof(buffer);
1026     r = MsiRecordGetString(hrec, 3, buffer, &sz);
1027     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1028     ok(!lstrcmp(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
1029
1030     r = MsiCloseHandle(hrec);
1031     ok(r == ERROR_SUCCESS, "failed to close record\n");
1032
1033     /* use a record that doesn't come from a view fetch */
1034     hrec = MsiCreateRecord(3);
1035     ok(hrec != 0, "MsiCreateRecord failed\n");
1036
1037     r = MsiRecordSetInteger(hrec, 1, 3);
1038     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1039     r = MsiRecordSetString(hrec, 2, "jane");
1040     ok(r == ERROR_SUCCESS, "failed to set string\n");
1041     r = MsiRecordSetString(hrec, 3, "112358");
1042     ok(r == ERROR_SUCCESS, "failed to set string\n");
1043
1044     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1045     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
1046
1047     r = MsiCloseHandle(hrec);
1048     ok(r == ERROR_SUCCESS, "failed to close record\n");
1049
1050     /* use a record that doesn't come from a view fetch, primary key matches */
1051     hrec = MsiCreateRecord(3);
1052     ok(hrec != 0, "MsiCreateRecord failed\n");
1053
1054     r = MsiRecordSetInteger(hrec, 1, 1);
1055     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1056     r = MsiRecordSetString(hrec, 2, "jane");
1057     ok(r == ERROR_SUCCESS, "failed to set string\n");
1058     r = MsiRecordSetString(hrec, 3, "112358");
1059     ok(r == ERROR_SUCCESS, "failed to set string\n");
1060
1061     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1062     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1063
1064     r = MsiCloseHandle(hrec);
1065     ok(r == ERROR_SUCCESS, "failed to close record\n");
1066
1067     hrec = MsiCreateRecord(3);
1068
1069     r = MsiRecordSetInteger(hrec, 1, 2);
1070     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1071     r = MsiRecordSetString(hrec, 2, "nick");
1072     ok(r == ERROR_SUCCESS, "failed to set string\n");
1073     r = MsiRecordSetString(hrec, 3, "141421");
1074     ok(r == ERROR_SUCCESS, "failed to set string\n");
1075
1076     r = MsiViewExecute(hview, 0);
1077     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1078     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
1079     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1080
1081     r = MsiCloseHandle(hrec);
1082     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1083     r = MsiViewClose(hview);
1084     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1085     r = MsiCloseHandle(hview);
1086     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1087
1088     query = "SELECT * FROM `phone` WHERE `id` = 1";
1089     r = MsiDatabaseOpenView(hdb, query, &hview);
1090     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1091     r = MsiViewExecute(hview, 0);
1092     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1093     r = MsiViewFetch(hview, &hrec);
1094     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1095
1096     /* change the id to match the second row */
1097     r = MsiRecordSetInteger(hrec, 1, 2);
1098     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1099     r = MsiRecordSetString(hrec, 2, "jerry");
1100     ok(r == ERROR_SUCCESS, "failed to set string\n");
1101
1102     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1103     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1104
1105     r = MsiCloseHandle(hrec);
1106     ok(r == ERROR_SUCCESS, "failed to close record\n");
1107     r = MsiViewClose(hview);
1108     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1109     r = MsiCloseHandle(hview);
1110     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1111
1112     /* broader search */
1113     query = "SELECT * FROM `phone` ORDER BY `id`";
1114     r = MsiDatabaseOpenView(hdb, query, &hview);
1115     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1116     r = MsiViewExecute(hview, 0);
1117     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1118     r = MsiViewFetch(hview, &hrec);
1119     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1120
1121     /* change the id to match the second row */
1122     r = MsiRecordSetInteger(hrec, 1, 2);
1123     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1124     r = MsiRecordSetString(hrec, 2, "jerry");
1125     ok(r == ERROR_SUCCESS, "failed to set string\n");
1126
1127     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1128     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1129
1130     r = MsiCloseHandle(hrec);
1131     ok(r == ERROR_SUCCESS, "failed to close record\n");
1132     r = MsiViewClose(hview);
1133     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1134     r = MsiCloseHandle(hview);
1135     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1136
1137     r = MsiCloseHandle( hdb );
1138     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1139 }
1140
1141 static MSIHANDLE create_db(void)
1142 {
1143     MSIHANDLE hdb = 0;
1144     UINT res;
1145
1146     DeleteFile(msifile);
1147
1148     /* create an empty database */
1149     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1150     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1151     if( res != ERROR_SUCCESS )
1152         return hdb;
1153
1154     res = MsiDatabaseCommit( hdb );
1155     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1156
1157     return hdb;
1158 }
1159
1160 static void test_getcolinfo(void)
1161 {
1162     MSIHANDLE hdb, hview = 0, rec = 0;
1163     UINT r;
1164     DWORD sz;
1165     char buffer[0x20];
1166
1167     /* create an empty db */
1168     hdb = create_db();
1169     ok( hdb, "failed to create db\n");
1170
1171     /* tables should be present */
1172     r = MsiDatabaseOpenView(hdb, "select * from _Tables", &hview);
1173     ok( r == ERROR_SUCCESS, "failed to open query\n");
1174
1175     r = MsiViewExecute(hview, 0);
1176     ok( r == ERROR_SUCCESS, "failed to execute query\n");
1177
1178     /* check that NAMES works */
1179     rec = 0;
1180     r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1181     ok( r == ERROR_SUCCESS, "failed to get names\n");
1182     sz = sizeof buffer;
1183     r = MsiRecordGetString(rec, 1, buffer, &sz );
1184     ok( r == ERROR_SUCCESS, "failed to get string\n");
1185     ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
1186     r = MsiCloseHandle( rec );
1187     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1188
1189     /* check that TYPES works */
1190     rec = 0;
1191     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1192     ok( r == ERROR_SUCCESS, "failed to get names\n");
1193     sz = sizeof buffer;
1194     r = MsiRecordGetString(rec, 1, buffer, &sz );
1195     ok( r == ERROR_SUCCESS, "failed to get string\n");
1196     ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
1197     r = MsiCloseHandle( rec );
1198     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1199
1200     /* check that invalid values fail */
1201     rec = 0;
1202     r = MsiViewGetColumnInfo( hview, 100, &rec );
1203     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1204     ok( rec == 0, "returned a record\n");
1205
1206     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1207     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1208
1209     r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1210     ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1211
1212     r = MsiViewClose(hview);
1213     ok( r == ERROR_SUCCESS, "failed to close view\n");
1214     r = MsiCloseHandle(hview);
1215     ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1216     r = MsiCloseHandle(hdb);
1217     ok( r == ERROR_SUCCESS, "failed to close database\n");
1218 }
1219
1220 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1221 {
1222     MSIHANDLE hview = 0, rec = 0;
1223     UINT r;
1224
1225     r = MsiDatabaseOpenView(hdb, query, &hview);
1226     if( r != ERROR_SUCCESS )
1227         return r;
1228
1229     r = MsiViewExecute(hview, 0);
1230     if( r == ERROR_SUCCESS )
1231     {
1232         MsiViewGetColumnInfo( hview, type, &rec );
1233     }
1234     MsiViewClose(hview);
1235     MsiCloseHandle(hview);
1236     return rec;
1237 }
1238
1239 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1240 {
1241     MSIHANDLE hview = 0, rec = 0;
1242     UINT r, type = 0;
1243     char query[0x100];
1244
1245     sprintf(query, "select * from `_Columns` where  `Table` = '%s'", table );
1246
1247     r = MsiDatabaseOpenView(hdb, query, &hview);
1248     if( r != ERROR_SUCCESS )
1249         return r;
1250
1251     r = MsiViewExecute(hview, 0);
1252     if( r == ERROR_SUCCESS )
1253     {
1254         while (1)
1255         {
1256             r = MsiViewFetch( hview, &rec );
1257             if( r != ERROR_SUCCESS)
1258                 break;
1259             r = MsiRecordGetInteger( rec, 2 );
1260             if (r == field)
1261                 type = MsiRecordGetInteger( rec, 4 );
1262             MsiCloseHandle( rec );
1263         }
1264     }
1265     MsiViewClose(hview);
1266     MsiCloseHandle(hview);
1267     return type;
1268 }
1269
1270 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
1271 {
1272     CHAR buffer[0x20];
1273     UINT r;
1274     DWORD sz;
1275
1276     sz = sizeof buffer;
1277     r = MsiRecordGetString( rec, field, buffer, &sz );
1278     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1279 }
1280
1281 static void test_viewgetcolumninfo(void)
1282 {
1283     MSIHANDLE hdb = 0, rec;
1284     UINT r;
1285
1286     hdb = create_db();
1287     ok( hdb, "failed to create db\n");
1288
1289     r = run_query( hdb, 0,
1290             "CREATE TABLE `Properties` "
1291             "( `Property` CHAR(255), "
1292             "  `Value` CHAR(1), "
1293             "  `Intvalue` INT, "
1294             "  `Integervalue` INTEGER, "
1295             "  `Shortvalue` SHORT, "
1296             "  `Longvalue` LONG, "
1297             "  `Longcharvalue` LONGCHAR "
1298             "  PRIMARY KEY `Property`)" );
1299     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1300
1301     /* check the column types */
1302     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1303     ok( rec, "failed to get column info record\n" );
1304
1305     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1306     ok( check_record( rec, 2, "S1"), "wrong record type\n");
1307     ok( check_record( rec, 3, "I2"), "wrong record type\n");
1308     ok( check_record( rec, 4, "I2"), "wrong record type\n");
1309     ok( check_record( rec, 5, "I2"), "wrong record type\n");
1310     ok( check_record( rec, 6, "I4"), "wrong record type\n");
1311     ok( check_record( rec, 7, "S0"), "wrong record type\n");
1312
1313     MsiCloseHandle( rec );
1314
1315     /* check the type in _Columns */
1316     ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1317     ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1318     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1319     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1320     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1321     ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1322     ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1323
1324     /* now try the names */
1325     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1326     ok( rec, "failed to get column info record\n" );
1327
1328     ok( check_record( rec, 1, "Property"), "wrong record type\n");
1329     ok( check_record( rec, 2, "Value"), "wrong record type\n");
1330     ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
1331     ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
1332     ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
1333     ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
1334     ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
1335
1336     MsiCloseHandle( rec );
1337
1338     r = run_query( hdb, 0,
1339             "CREATE TABLE `Binary` "
1340             "( `Name` CHAR(255), `Data` OBJECT  PRIMARY KEY `Name`)" );
1341     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1342
1343     /* check the column types */
1344     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1345     ok( rec, "failed to get column info record\n" );
1346
1347     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1348     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1349
1350     MsiCloseHandle( rec );
1351
1352     /* check the type in _Columns */
1353     ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1354     ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1355
1356     /* now try the names */
1357     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1358     ok( rec, "failed to get column info record\n" );
1359
1360     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1361     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1362     MsiCloseHandle( rec );
1363
1364     r = run_query( hdb, 0,
1365             "CREATE TABLE `UIText` "
1366             "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1367     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1368
1369     ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1370     ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1371
1372     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1373     ok( rec, "failed to get column info record\n" );
1374     ok( check_record( rec, 1, "Key"), "wrong record type\n");
1375     ok( check_record( rec, 2, "Text"), "wrong record type\n");
1376     MsiCloseHandle( rec );
1377
1378     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1379     ok( rec, "failed to get column info record\n" );
1380     ok( check_record( rec, 1, "s72"), "wrong record type\n");
1381     ok( check_record( rec, 2, "L255"), "wrong record type\n");
1382     MsiCloseHandle( rec );
1383
1384     MsiCloseHandle( hdb );
1385 }
1386
1387 static void test_msiexport(void)
1388 {
1389     MSIHANDLE hdb = 0, hview = 0;
1390     UINT r;
1391     const char *query;
1392     char path[MAX_PATH];
1393     const char file[] = "phone.txt";
1394     HANDLE handle;
1395     char buffer[0x100];
1396     DWORD length;
1397     const char expected[] =
1398         "id\tname\tnumber\r\n"
1399         "I2\tS32\tS32\r\n"
1400         "phone\tid\r\n"
1401         "1\tAbe\t8675309\r\n";
1402
1403     DeleteFile(msifile);
1404
1405     /* just MsiOpenDatabase should not create a file */
1406     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1407     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1408
1409     /* create a table */
1410     query = "CREATE TABLE `phone` ( "
1411             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1412             "PRIMARY KEY `id`)";
1413     r = MsiDatabaseOpenView(hdb, query, &hview);
1414     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1415     r = MsiViewExecute(hview, 0);
1416     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1417     r = MsiViewClose(hview);
1418     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1419     r = MsiCloseHandle(hview);
1420     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1421
1422     /* insert a value into it */
1423     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1424         "VALUES('1', 'Abe', '8675309')";
1425     r = MsiDatabaseOpenView(hdb, query, &hview);
1426     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1427     r = MsiViewExecute(hview, 0);
1428     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1429     r = MsiViewClose(hview);
1430     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1431     r = MsiCloseHandle(hview);
1432     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1433
1434     GetCurrentDirectory(MAX_PATH, path);
1435
1436     r = MsiDatabaseExport(hdb, "phone", path, file);
1437     ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1438
1439     MsiCloseHandle(hdb);
1440
1441     lstrcat(path, "\\");
1442     lstrcat(path, file);
1443
1444     /* check the data that was written */
1445     length = 0;
1446     memset(buffer, 0, sizeof buffer);
1447     handle = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1448     if (handle != INVALID_HANDLE_VALUE)
1449     {
1450         ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1451         CloseHandle(handle);
1452         DeleteFile(path);
1453     }
1454     else
1455         ok(0, "failed to open file %s\n", path);
1456
1457     ok( length == strlen(expected), "length of data wrong\n");
1458     ok( !lstrcmp(buffer, expected), "data doesn't match\n");
1459     DeleteFile(msifile);
1460 }
1461
1462 static void test_longstrings(void)
1463 {
1464     const char insert_query[] = 
1465         "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1466     char *str;
1467     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1468     DWORD len;
1469     UINT r;
1470     const DWORD STRING_LENGTH = 0x10005;
1471
1472     DeleteFile(msifile);
1473     /* just MsiOpenDatabase should not create a file */
1474     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1475     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1476
1477     /* create a table */
1478     r = try_query( hdb, 
1479         "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1480     ok(r == ERROR_SUCCESS, "query failed\n");
1481
1482     /* try a insert a very long string */
1483     str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
1484     len = strchr(insert_query, 'Z') - insert_query;
1485     strcpy(str, insert_query);
1486     memset(str+len, 'Z', STRING_LENGTH);
1487     strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1488     r = try_query( hdb, str );
1489     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1490
1491     HeapFree(GetProcessHeap(), 0, str);
1492
1493     r = MsiDatabaseCommit(hdb);
1494     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1495     MsiCloseHandle(hdb);
1496
1497     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
1498     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1499
1500     r = MsiDatabaseOpenView(hdb, "select * from `strings` where `id` = 1", &hview);
1501     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1502
1503     r = MsiViewExecute(hview, 0);
1504     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1505
1506     r = MsiViewFetch(hview, &hrec);
1507     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1508
1509     MsiViewClose(hview);
1510     MsiCloseHandle(hview);
1511
1512     r = MsiRecordGetString(hrec, 2, NULL, &len);
1513     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1514     ok(len == STRING_LENGTH, "string length wrong\n");
1515
1516     MsiCloseHandle(hrec);
1517     MsiCloseHandle(hdb);
1518     DeleteFile(msifile);
1519 }
1520
1521 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1522 {
1523     HANDLE file;
1524     DWORD written;
1525
1526     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1527     if (file == INVALID_HANDLE_VALUE)
1528         return;
1529
1530     WriteFile(file, data, strlen(data), &written, NULL);
1531     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1532
1533     if (size)
1534     {
1535         SetFilePointer(file, size, NULL, FILE_BEGIN);
1536         SetEndOfFile(file);
1537     }
1538
1539     CloseHandle(file);
1540 }
1541
1542 #define create_file(name) create_file_data(name, name, 0)
1543  
1544 static void test_streamtable(void)
1545 {
1546     MSIHANDLE hdb = 0, rec, view, hsi;
1547     char file[MAX_PATH];
1548     char buf[MAX_PATH];
1549     DWORD size;
1550     UINT r;
1551
1552     hdb = create_db();
1553     ok( hdb, "failed to create db\n");
1554
1555     r = run_query( hdb, 0,
1556             "CREATE TABLE `Properties` "
1557             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
1558     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1559
1560     r = run_query( hdb, 0,
1561             "INSERT INTO `Properties` "
1562             "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1563     ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1564
1565     r = MsiDatabaseCommit( hdb );
1566     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1567
1568     MsiCloseHandle( hdb );
1569
1570     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
1571     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1572
1573     /* check the column types */
1574     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1575     ok( rec, "failed to get column info record\n" );
1576
1577     ok( check_record( rec, 1, "s62"), "wrong record type\n");
1578     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1579
1580     MsiCloseHandle( rec );
1581
1582     /* now try the names */
1583     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1584     ok( rec, "failed to get column info record\n" );
1585
1586     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1587     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1588
1589     MsiCloseHandle( rec );
1590
1591     r = MsiDatabaseOpenView( hdb,
1592             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1593     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1594
1595     r = MsiViewExecute( view, 0 );
1596     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1597
1598     r = MsiViewFetch( view, &rec );
1599     ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1600
1601     MsiCloseHandle( rec );
1602     MsiViewClose( view );
1603     MsiCloseHandle( view );
1604
1605     /* create a summary information stream */
1606     r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1607     ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1608
1609     r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1610     ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1611
1612     r = MsiSummaryInfoPersist( hsi );
1613     ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1614
1615     MsiCloseHandle( hsi );
1616
1617     r = MsiDatabaseOpenView( hdb,
1618             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1619     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1620
1621     r = MsiViewExecute( view, 0 );
1622     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1623
1624     r = MsiViewFetch( view, &rec );
1625     ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1626
1627     MsiCloseHandle( rec );
1628     MsiViewClose( view );
1629     MsiCloseHandle( view );
1630
1631     /* insert a file into the _Streams table */
1632     create_file( "test.txt" );
1633
1634     rec = MsiCreateRecord( 2 );
1635     MsiRecordSetString( rec, 1, "data" );
1636
1637     r = MsiRecordSetStream( rec, 2, "test.txt" );
1638     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1639
1640     DeleteFile("test.txt");
1641
1642     r = MsiDatabaseOpenView( hdb,
1643             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1644     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1645
1646     r = MsiViewExecute( view, rec );
1647     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1648
1649     MsiCloseHandle( rec );
1650     MsiViewClose( view );
1651     MsiCloseHandle( view );
1652
1653     /* insert another one */
1654     create_file( "test1.txt" );
1655
1656     rec = MsiCreateRecord( 2 );
1657     MsiRecordSetString( rec, 1, "data1" );
1658
1659     r = MsiRecordSetStream( rec, 2, "test1.txt" );
1660     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1661
1662     DeleteFile("test1.txt");
1663
1664     r = MsiDatabaseOpenView( hdb,
1665             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1666     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1667
1668     r = MsiViewExecute( view, rec );
1669     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1670
1671     MsiCloseHandle( rec );
1672     MsiViewClose( view );
1673     MsiCloseHandle( view );
1674
1675     r = MsiDatabaseOpenView( hdb,
1676             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1677     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1678
1679     r = MsiViewExecute( view, 0 );
1680     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1681
1682     r = MsiViewFetch( view, &rec );
1683     ok( r == ERROR_SUCCESS, "Failed to fetch record: %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, "data"), "Expected 'data', 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     MsiCloseHandle( rec );
1697     MsiViewClose( view );
1698     MsiCloseHandle( view );
1699
1700     r = MsiDatabaseOpenView( hdb,
1701             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1702     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1703
1704     r = MsiViewExecute( view, 0 );
1705     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1706
1707     r = MsiViewFetch( view, &rec );
1708     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1709
1710     size = MAX_PATH;
1711     r = MsiRecordGetString( rec, 1, file, &size );
1712     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1713     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1714
1715     size = MAX_PATH;
1716     memset(buf, 0, MAX_PATH);
1717     r = MsiRecordReadStream( rec, 2, buf, &size );
1718     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1719     ok( !lstrcmp(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
1720
1721     MsiCloseHandle( rec );
1722     MsiViewClose( view );
1723     MsiCloseHandle( view );
1724
1725     /* perform an update */
1726     create_file( "test2.txt" );
1727     rec = MsiCreateRecord( 1 );
1728
1729     r = MsiRecordSetStream( rec, 1, "test2.txt" );
1730     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1731
1732     DeleteFile("test2.txt");
1733
1734     r = MsiDatabaseOpenView( hdb,
1735             "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1736     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1737
1738     r = MsiViewExecute( view, rec );
1739     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1740
1741     MsiCloseHandle( rec );
1742     MsiViewClose( view );
1743     MsiCloseHandle( view );
1744
1745     r = MsiDatabaseOpenView( hdb,
1746             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1747     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1748
1749     r = MsiViewExecute( view, 0 );
1750     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1751
1752     r = MsiViewFetch( view, &rec );
1753     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1754
1755     size = MAX_PATH;
1756     r = MsiRecordGetString( rec, 1, file, &size );
1757     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1758     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1759
1760     size = MAX_PATH;
1761     memset(buf, 0, MAX_PATH);
1762     r = MsiRecordReadStream( rec, 2, buf, &size );
1763     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1764     todo_wine ok( !lstrcmp(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
1765
1766     MsiCloseHandle( rec );
1767     MsiViewClose( view );
1768     MsiCloseHandle( view );
1769     MsiCloseHandle( hdb );
1770     DeleteFile(msifile);
1771 }
1772
1773 static void test_binary(void)
1774 {
1775     MSIHANDLE hdb = 0, rec;
1776     char file[MAX_PATH];
1777     char buf[MAX_PATH];
1778     DWORD size;
1779     LPCSTR query;
1780     UINT r;
1781
1782     /* insert a file into the Binary table */
1783     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1784     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1785
1786     query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
1787     r = run_query( hdb, 0, query );
1788     ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1789
1790     create_file( "test.txt" );
1791     rec = MsiCreateRecord( 1 );
1792     r = MsiRecordSetStream( rec, 1, "test.txt" );
1793     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1794     DeleteFile( "test.txt" );
1795
1796     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1797     r = run_query( hdb, rec, query );
1798     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1799
1800     r = MsiCloseHandle( rec );
1801     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1802
1803     r = MsiDatabaseCommit( hdb );
1804     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1805
1806     r = MsiCloseHandle( hdb );
1807     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1808
1809     /* read file from the Stream table */
1810     r = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
1811     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1812
1813     query = "SELECT * FROM `_Streams`";
1814     r = do_query( hdb, query, &rec );
1815     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1816
1817     size = MAX_PATH;
1818     r = MsiRecordGetString( rec, 1, file, &size );
1819     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1820     ok( !lstrcmp(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1821
1822     size = MAX_PATH;
1823     memset( buf, 0, MAX_PATH );
1824     r = MsiRecordReadStream( rec, 2, buf, &size );
1825     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1826     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1827
1828     r = MsiCloseHandle( rec );
1829     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1830
1831     /* read file from the Binary table */
1832     query = "SELECT * FROM `Binary`";
1833     r = do_query( hdb, query, &rec );
1834     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1835
1836     size = MAX_PATH;
1837     r = MsiRecordGetString( rec, 1, file, &size );
1838     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1839     ok( !lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file );
1840
1841     size = MAX_PATH;
1842     memset( buf, 0, MAX_PATH );
1843     r = MsiRecordReadStream( rec, 3, buf, &size );
1844     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1845     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1846
1847     r = MsiCloseHandle( rec );
1848     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1849
1850     r = MsiCloseHandle( hdb );
1851     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1852
1853     DeleteFile( msifile );
1854 }
1855
1856 static void test_where_not_in_selected(void)
1857 {
1858     MSIHANDLE hdb = 0, rec, view;
1859     LPCSTR query;
1860     UINT r;
1861
1862     hdb = create_db();
1863     ok( hdb, "failed to create db\n");
1864
1865     r = run_query(hdb, 0,
1866             "CREATE TABLE `IESTable` ("
1867             "`Action` CHAR(64), "
1868             "`Condition` CHAR(64), "
1869             "`Sequence` LONG PRIMARY KEY `Sequence`)");
1870     ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1871
1872     r = run_query(hdb, 0,
1873             "CREATE TABLE `CATable` ("
1874             "`Action` CHAR(64), "
1875             "`Type` LONG PRIMARY KEY `Type`)");
1876     ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1877
1878     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1879             "( `Action`, `Condition`, `Sequence`) "
1880             "VALUES ( 'clean', 'cond4', 4)");
1881     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1882
1883     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1884             "( `Action`, `Condition`, `Sequence`) "
1885             "VALUES ( 'depends', 'cond1', 1)");
1886     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1887
1888     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1889             "( `Action`, `Condition`, `Sequence`) "
1890             "VALUES ( 'build', 'cond2', 2)");
1891     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1892
1893     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1894             "( `Action`, `Condition`, `Sequence`) "
1895             "VALUES ( 'build2', 'cond6', 6)");
1896     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1897
1898     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1899             "( `Action`, `Condition`, `Sequence`) "
1900             "VALUES ( 'build', 'cond3', 3)");
1901     ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1902
1903     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1904             "( `Action`, `Type` ) "
1905             "VALUES ( 'build', 32)");
1906     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1907
1908     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1909             "( `Action`, `Type` ) "
1910             "VALUES ( 'depends', 64)");
1911     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1912
1913     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1914             "( `Action`, `Type` ) "
1915             "VALUES ( 'clean', 63)");
1916     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1917
1918     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1919             "( `Action`, `Type` ) "
1920             "VALUES ( 'build2', 34)");
1921     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1922     query = "Select IESTable.Condition from CATable, IESTable where "
1923             "CATable.Action = IESTable.Action and CATable.Type = 32";
1924     r = MsiDatabaseOpenView(hdb, query, &view);
1925     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1926
1927     r = MsiViewExecute(view, 0);
1928     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1929
1930     r = MsiViewFetch(view, &rec);
1931     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1932
1933     ok( check_record( rec, 1, "cond2"), "wrong condition\n");
1934
1935     MsiCloseHandle( rec );
1936     r = MsiViewFetch(view, &rec);
1937     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1938
1939     ok( check_record( rec, 1, "cond3"), "wrong condition\n");
1940
1941     MsiCloseHandle( rec );
1942     MsiViewClose(view);
1943     MsiCloseHandle(view);
1944
1945     MsiCloseHandle( hdb );
1946     DeleteFile(msifile);
1947
1948 }
1949
1950
1951 static void test_where(void)
1952 {
1953     MSIHANDLE hdb = 0, rec, view;
1954     LPCSTR query;
1955     UINT r;
1956     DWORD size;
1957     CHAR buf[MAX_PATH];
1958     UINT count;
1959
1960     hdb = create_db();
1961     ok( hdb, "failed to create db\n");
1962
1963     r = run_query( hdb, 0,
1964             "CREATE TABLE `Media` ("
1965             "`DiskId` SHORT NOT NULL, "
1966             "`LastSequence` LONG, "
1967             "`DiskPrompt` CHAR(64) LOCALIZABLE, "
1968             "`Cabinet` CHAR(255), "
1969             "`VolumeLabel` CHAR(32), "
1970             "`Source` CHAR(72) "
1971             "PRIMARY KEY `DiskId`)" );
1972     ok( r == S_OK, "cannot create Media table: %d\n", r );
1973
1974     r = run_query( hdb, 0, "INSERT INTO `Media` "
1975             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1976             "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
1977     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1978
1979     r = run_query( hdb, 0, "INSERT INTO `Media` "
1980             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1981             "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
1982     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1983
1984     r = run_query( hdb, 0, "INSERT INTO `Media` "
1985             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1986             "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
1987     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1988
1989     query = "SELECT * FROM `Media`";
1990     r = do_query(hdb, query, &rec);
1991     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1992     ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
1993     MsiCloseHandle( rec );
1994
1995     query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
1996     r = do_query(hdb, query, &rec);
1997     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1998     ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
1999
2000     r = MsiRecordGetInteger(rec, 1);
2001     ok( 2 == r, "field wrong\n");
2002     r = MsiRecordGetInteger(rec, 2);
2003     ok( 1 == r, "field wrong\n");
2004     MsiCloseHandle( rec );
2005
2006     query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
2007     r = MsiDatabaseOpenView(hdb, query, &view);
2008     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
2009
2010     r = MsiViewExecute(view, 0);
2011     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
2012
2013     r = MsiViewFetch(view, &rec);
2014     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2015
2016     count = MsiRecordGetFieldCount( rec );
2017     ok( count == 1, "Expected 1 record fields, got %d\n", count );
2018
2019     size = MAX_PATH;
2020     r = MsiRecordGetString( rec, 1, buf, &size );
2021     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2022     ok( !lstrcmp( buf, "2" ),
2023         "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
2024     MsiCloseHandle( rec );
2025
2026     r = MsiViewFetch(view, &rec);
2027     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2028
2029     size = MAX_PATH;
2030     r = MsiRecordGetString( rec, 1, buf, &size );
2031     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2032     ok( !lstrcmp( buf, "3" ),
2033         "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
2034     MsiCloseHandle( rec );
2035
2036     r = MsiViewFetch(view, &rec);
2037     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
2038
2039     MsiViewClose(view);
2040     MsiCloseHandle(view);
2041
2042     MsiCloseHandle( rec );
2043
2044     rec = 0;
2045     query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
2046     r = do_query(hdb, query, &rec);
2047     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2048     MsiCloseHandle( rec );
2049
2050     rec = 0;
2051     query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
2052     r = do_query(hdb, query, &rec);
2053     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2054     MsiCloseHandle( rec );
2055
2056     rec = 0;
2057     query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
2058     r = do_query(hdb, query, &rec);
2059     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2060     MsiCloseHandle( rec );
2061
2062     rec = 0;
2063     query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
2064     r = do_query(hdb, query, &rec);
2065     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2066     MsiCloseHandle( rec );
2067
2068     rec = 0;
2069     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
2070     r = do_query(hdb, query, &rec);
2071     ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
2072     MsiCloseHandle( rec );
2073
2074     rec = MsiCreateRecord(1);
2075     MsiRecordSetString(rec, 1, "");
2076
2077     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
2078     r = MsiDatabaseOpenView(hdb, query, &view);
2079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2080     r = MsiViewExecute(view, rec);
2081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2082
2083     MsiCloseHandle(rec);
2084
2085     r = MsiViewFetch(view, &rec);
2086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2087
2088     MsiCloseHandle(rec);
2089     MsiViewClose(view);
2090     MsiCloseHandle(view);
2091
2092     MsiCloseHandle( hdb );
2093     DeleteFile(msifile);
2094 }
2095
2096 static CHAR CURR_DIR[MAX_PATH];
2097
2098 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
2099                                 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
2100                                 "TestTable\tFirstPrimaryColumn\n"
2101                                 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
2102
2103 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
2104                                   "s255\ts255\n"
2105                                   "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
2106                                   "papaya\tleaf\n"
2107                                   "papaya\tflower\n";
2108
2109 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
2110                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2111                                 "Table\tA\r\n"
2112                                 "a\tb\tc\td\te\tf\n"
2113                                 "g\th\ti\t\rj\tk\tl\r\n";
2114
2115 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
2116                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2117                                 "Table2\tA\r\n"
2118                                 "a\tb\tc\td\te\tf\n"
2119                                 "g\th\ti\tj\tk\tl\r\n";
2120
2121 static const CHAR suminfo[] = "PropertyId\tValue\n"
2122                               "i2\tl255\n"
2123                               "_SummaryInformation\tPropertyId\n"
2124                               "1\t1252\n"
2125                               "2\tInstaller Database\n"
2126                               "3\tInstaller description\n"
2127                               "4\tWineHQ\n"
2128                               "5\tInstaller\n"
2129                               "6\tInstaller comments\n"
2130                               "7\tIntel;1033,2057\n"
2131                               "9\t{12345678-1234-1234-1234-123456789012}\n"
2132                               "12\t2009/04/12 15:46:11\n"
2133                               "13\t2009/04/12 15:46:11\n"
2134                               "14\t200\n"
2135                               "15\t2\n"
2136                               "18\tVim\n"
2137                               "19\t2\n";
2138
2139 static void write_file(const CHAR *filename, const char *data, int data_size)
2140 {
2141     DWORD size;
2142
2143     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
2144                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2145
2146     WriteFile(hf, data, data_size, &size, NULL);
2147     CloseHandle(hf);
2148 }
2149
2150 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2151 {
2152     UINT r;
2153
2154     write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
2155     r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2156     DeleteFileA("temp_file");
2157
2158     return r;
2159 }
2160
2161 static void test_suminfo_import(void)
2162 {
2163     MSIHANDLE hdb, hsi, view = 0;
2164     LPCSTR query;
2165     UINT r, count, size, type;
2166     char str_value[50];
2167     INT int_value;
2168     FILETIME ft_value;
2169
2170     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2171
2172     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2174
2175     r = add_table_to_db(hdb, suminfo);
2176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2177
2178     /* _SummaryInformation is not imported as a regular table... */
2179
2180     query = "SELECT * FROM `_SummaryInformation`";
2181     r = MsiDatabaseOpenViewA(hdb, query, &view);
2182     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2183     MsiCloseHandle(view);
2184
2185     /* ...its data is added to the special summary information stream */
2186
2187     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2189
2190     r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2192     ok(count == 14, "Expected 14, got %u\n", count);
2193
2194     r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2196     ok(type ==  VT_I2, "Expected VT_I2, got %u\n", type);
2197     ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2198
2199     size = sizeof(str_value);
2200     r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2202     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2203     ok(size == 18, "Expected 18, got %u\n", size);
2204     ok(!strcmp(str_value, "Installer Database"),
2205        "Expected \"Installer Database\", got %s\n", str_value);
2206
2207     size = sizeof(str_value);
2208     r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2210     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2211     ok(!strcmp(str_value, "Installer description"),
2212        "Expected \"Installer description\", got %s\n", str_value);
2213
2214     size = sizeof(str_value);
2215     r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2217     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2218     ok(!strcmp(str_value, "WineHQ"),
2219        "Expected \"WineHQ\", got %s\n", str_value);
2220
2221     size = sizeof(str_value);
2222     r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2224     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2225     ok(!strcmp(str_value, "Installer"),
2226        "Expected \"Installer\", got %s\n", str_value);
2227
2228     size = sizeof(str_value);
2229     r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2231     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2232     ok(!strcmp(str_value, "Installer comments"),
2233        "Expected \"Installer comments\", got %s\n", str_value);
2234
2235     size = sizeof(str_value);
2236     r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2237     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2238     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2239     ok(!strcmp(str_value, "Intel;1033,2057"),
2240        "Expected \"Intel;1033,2057\", got %s\n", str_value);
2241
2242     size = sizeof(str_value);
2243     r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2245     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2246     ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2247        "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2248
2249     r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2251     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2252
2253     r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2255     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2256
2257     r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2259     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2260     ok(int_value == 200, "Expected 200, got %d\n", int_value);
2261
2262     r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2264     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2265     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2266
2267     r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2269     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2270     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2271
2272     size = sizeof(str_value);
2273     r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2275     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2276     ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2277
2278     MsiCloseHandle(hsi);
2279     MsiCloseHandle(hdb);
2280     DeleteFileA(msifile);
2281 }
2282
2283 static void test_msiimport(void)
2284 {
2285     MSIHANDLE hdb, view, rec;
2286     LPCSTR query;
2287     UINT r, count;
2288     signed int i;
2289
2290     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2291
2292     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2294
2295     r = add_table_to_db(hdb, test_data);
2296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2297
2298     r = add_table_to_db(hdb, two_primary);
2299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2300
2301     r = add_table_to_db(hdb, endlines1);
2302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2303
2304     r = add_table_to_db(hdb, endlines2);
2305     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2306
2307     query = "SELECT * FROM `TestTable`";
2308     r = MsiDatabaseOpenView(hdb, query, &view);
2309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2310
2311     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2313     count = MsiRecordGetFieldCount(rec);
2314     ok(count == 9, "Expected 9, got %d\n", count);
2315     ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2316     ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2317     ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2318     ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2319     ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2320     ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2321     ok(check_record(rec, 7, "String"), "Expected String\n");
2322     ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2323     ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2324     MsiCloseHandle(rec);
2325
2326     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2328     count = MsiRecordGetFieldCount(rec);
2329     ok(count == 9, "Expected 9, got %d\n", count);
2330     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2331     ok(check_record(rec, 2, "i2"), "Expected i2\n");
2332     ok(check_record(rec, 3, "i2"), "Expected i2\n");
2333     ok(check_record(rec, 4, "I2"), "Expected I2\n");
2334     ok(check_record(rec, 5, "i4"), "Expected i4\n");
2335     ok(check_record(rec, 6, "I4"), "Expected I4\n");
2336     ok(check_record(rec, 7, "S255"), "Expected S255\n");
2337     ok(check_record(rec, 8, "S0"), "Expected S0\n");
2338     ok(check_record(rec, 9, "s0"), "Expected s0\n");
2339     MsiCloseHandle(rec);
2340
2341     query = "SELECT * FROM `TestTable`";
2342     r = do_query(hdb, query, &rec);
2343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2344     ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2345     ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2346     ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2347     ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2348
2349     i = MsiRecordGetInteger(rec, 2);
2350     ok(i == 5, "Expected 5, got %d\n", i);
2351
2352     i = MsiRecordGetInteger(rec, 3);
2353     ok(i == 2, "Expected 2, got %d\n", i);
2354
2355     i = MsiRecordGetInteger(rec, 4);
2356     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2357
2358     i = MsiRecordGetInteger(rec, 5);
2359     ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2360
2361     i = MsiRecordGetInteger(rec, 6);
2362     ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2363
2364     MsiCloseHandle(rec);
2365     MsiViewClose(view);
2366     MsiCloseHandle(view);
2367
2368     query = "SELECT * FROM `TwoPrimary`";
2369     r = MsiDatabaseOpenView(hdb, query, &view);
2370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2371
2372     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2374     count = MsiRecordGetFieldCount(rec);
2375     ok(count == 2, "Expected 2, got %d\n", count);
2376     ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2377     ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2378
2379     MsiCloseHandle(rec);
2380
2381     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2383     count = MsiRecordGetFieldCount(rec);
2384     ok(count == 2, "Expected 2, got %d\n", count);
2385     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2386     ok(check_record(rec, 2, "s255"), "Expected s255\n");
2387     MsiCloseHandle(rec);
2388
2389     r = MsiViewExecute(view, 0);
2390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2391
2392     r = MsiViewFetch(view, &rec);
2393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2394
2395     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2396     ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2397
2398     MsiCloseHandle(rec);
2399
2400     r = MsiViewFetch(view, &rec);
2401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2402
2403     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2404     ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2405
2406     MsiCloseHandle(rec);
2407
2408     r = MsiViewFetch(view, &rec);
2409     ok(r == ERROR_NO_MORE_ITEMS,
2410        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2411
2412     r = MsiViewClose(view);
2413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2414
2415     MsiCloseHandle(view);
2416
2417     query = "SELECT * FROM `Table`";
2418     r = MsiDatabaseOpenView(hdb, query, &view);
2419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2420
2421     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2423     count = MsiRecordGetFieldCount(rec);
2424     ok(count == 6, "Expected 6, got %d\n", count);
2425     ok(check_record(rec, 1, "A"), "Expected A\n");
2426     ok(check_record(rec, 2, "B"), "Expected B\n");
2427     ok(check_record(rec, 3, "C"), "Expected C\n");
2428     ok(check_record(rec, 4, "D"), "Expected D\n");
2429     ok(check_record(rec, 5, "E"), "Expected E\n");
2430     ok(check_record(rec, 6, "F"), "Expected F\n");
2431     MsiCloseHandle(rec);
2432
2433     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2435     count = MsiRecordGetFieldCount(rec);
2436     ok(count == 6, "Expected 6, got %d\n", count);
2437     ok(check_record(rec, 1, "s72"), "Expected s72\n");
2438     ok(check_record(rec, 2, "s72"), "Expected s72\n");
2439     ok(check_record(rec, 3, "s72"), "Expected s72\n");
2440     ok(check_record(rec, 4, "s72"), "Expected s72\n");
2441     ok(check_record(rec, 5, "s72"), "Expected s72\n");
2442     ok(check_record(rec, 6, "s72"), "Expected s72\n");
2443     MsiCloseHandle(rec);
2444
2445     MsiViewClose(view);
2446     MsiCloseHandle(view);
2447
2448     query = "SELECT * FROM `Table`";
2449     r = MsiDatabaseOpenView(hdb, query, &view);
2450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2451
2452     r = MsiViewExecute(view, 0);
2453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2454
2455     r = MsiViewFetch(view, &rec);
2456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2457     ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2458     ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2459     ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2460     ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2461     ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2462     ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2463
2464     MsiCloseHandle(rec);
2465
2466     r = MsiViewFetch(view, &rec);
2467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2468     ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2469     ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2470     ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2471     ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2472     ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2473     ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2474
2475     MsiCloseHandle(rec);
2476
2477     r = MsiViewFetch(view, &rec);
2478     ok(r == ERROR_NO_MORE_ITEMS,
2479        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2480
2481     MsiViewClose(view);
2482     MsiCloseHandle(view);
2483     MsiCloseHandle(hdb);
2484     DeleteFileA(msifile);
2485 }
2486
2487 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2488                                      "s72\tV0\r\n"
2489                                      "Binary\tName\r\n"
2490                                      "filename1\tfilename1.ibd\r\n";
2491
2492 static void test_binary_import(void)
2493 {
2494     MSIHANDLE hdb = 0, rec;
2495     char file[MAX_PATH];
2496     char buf[MAX_PATH];
2497     char path[MAX_PATH];
2498     DWORD size;
2499     LPCSTR query;
2500     UINT r;
2501
2502     /* create files to import */
2503     write_file("bin_import.idt", bin_import_dat,
2504           (sizeof(bin_import_dat) - 1) * sizeof(char));
2505     CreateDirectory("bin_import", NULL);
2506     create_file_data("bin_import/filename1.ibd", "just some words", 15);
2507
2508     /* import files into database */
2509     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
2510     ok( r == ERROR_SUCCESS , "Failed to open database\n");
2511
2512     GetCurrentDirectory(MAX_PATH, path);
2513     r = MsiDatabaseImport(hdb, path, "bin_import.idt");
2514     ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2515
2516     /* read file from the Binary table */
2517     query = "SELECT * FROM `Binary`";
2518     r = do_query(hdb, query, &rec);
2519     ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2520
2521     size = MAX_PATH;
2522     r = MsiRecordGetString(rec, 1, file, &size);
2523     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2524     ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file);
2525
2526     size = MAX_PATH;
2527     memset(buf, 0, MAX_PATH);
2528     r = MsiRecordReadStream(rec, 2, buf, &size);
2529     ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2530     ok(!lstrcmp(buf, "just some words"),
2531         "Expected 'just some words', got %s\n", buf);
2532
2533     r = MsiCloseHandle(rec);
2534     ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2535
2536     r = MsiCloseHandle(hdb);
2537     ok(r == ERROR_SUCCESS , "Failed to close database\n");
2538
2539     DeleteFile("bin_import/filename1.ibd");
2540     RemoveDirectory("bin_import");
2541     DeleteFile("bin_import.idt");
2542 }
2543
2544 static void test_markers(void)
2545 {
2546     MSIHANDLE hdb, rec;
2547     LPCSTR query;
2548     UINT r;
2549
2550     hdb = create_db();
2551     ok( hdb, "failed to create db\n");
2552
2553     rec = MsiCreateRecord(3);
2554     MsiRecordSetString(rec, 1, "Table");
2555     MsiRecordSetString(rec, 2, "Apples");
2556     MsiRecordSetString(rec, 3, "Oranges");
2557
2558     /* try a legit create */
2559     query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2560     r = run_query(hdb, 0, query);
2561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2562     MsiCloseHandle(rec);
2563
2564     /* try table name as marker */
2565     rec = MsiCreateRecord(1);
2566     MsiRecordSetString(rec, 1, "Fable");
2567     query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2568     r = run_query(hdb, rec, query);
2569     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2570
2571     /* verify that we just created a table called '?', not 'Fable' */
2572     r = try_query(hdb, "SELECT * from `Fable`");
2573     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2574
2575     r = try_query(hdb, "SELECT * from `?`");
2576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2577
2578     /* try table name as marker without backticks */
2579     MsiRecordSetString(rec, 1, "Mable");
2580     query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2581     r = run_query(hdb, rec, query);
2582     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2583
2584     /* try one column name as marker */
2585     MsiRecordSetString(rec, 1, "One");
2586     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2587     r = run_query(hdb, rec, query);
2588     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2589     MsiCloseHandle(rec);
2590
2591     /* try column names as markers */
2592     rec = MsiCreateRecord(2);
2593     MsiRecordSetString(rec, 1, "One");
2594     MsiRecordSetString(rec, 2, "Two");
2595     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2596     r = run_query(hdb, rec, query);
2597     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2598     MsiCloseHandle(rec);
2599
2600     /* try names with backticks */
2601     rec = MsiCreateRecord(3);
2602     MsiRecordSetString(rec, 1, "One");
2603     MsiRecordSetString(rec, 2, "Two");
2604     MsiRecordSetString(rec, 3, "One");
2605     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2606     r = run_query(hdb, rec, query);
2607     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2608
2609     /* try names with backticks, minus definitions */
2610     query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2611     r = run_query(hdb, rec, query);
2612     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2613
2614     /* try names without backticks */
2615     query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2616     r = run_query(hdb, rec, query);
2617     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2618     MsiCloseHandle(rec);
2619
2620     /* try one long marker */
2621     rec = MsiCreateRecord(1);
2622     MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2623     query = "CREATE TABLE `Mable` ( ? )";
2624     r = run_query(hdb, rec, query);
2625     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2626     MsiCloseHandle(rec);
2627
2628     /* try all names as markers */
2629     rec = MsiCreateRecord(4);
2630     MsiRecordSetString(rec, 1, "Mable");
2631     MsiRecordSetString(rec, 2, "One");
2632     MsiRecordSetString(rec, 3, "Two");
2633     MsiRecordSetString(rec, 4, "One");
2634     query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2635     r = run_query(hdb, rec, query);
2636     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2637     MsiCloseHandle(rec);
2638
2639     /* try a legit insert */
2640     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2641     r = run_query(hdb, 0, query);
2642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2643
2644     r = try_query(hdb, "SELECT * from `Table`");
2645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2646
2647     /* try values as markers */
2648     rec = MsiCreateRecord(2);
2649     MsiRecordSetInteger(rec, 1, 4);
2650     MsiRecordSetString(rec, 2, "hi");
2651     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2652     r = run_query(hdb, rec, query);
2653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2654     MsiCloseHandle(rec);
2655
2656     /* try column names and values as markers */
2657     rec = MsiCreateRecord(4);
2658     MsiRecordSetString(rec, 1, "One");
2659     MsiRecordSetString(rec, 2, "Two");
2660     MsiRecordSetInteger(rec, 3, 5);
2661     MsiRecordSetString(rec, 4, "hi");
2662     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2663     r = run_query(hdb, rec, query);
2664     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2665     MsiCloseHandle(rec);
2666
2667     /* try column names as markers */
2668     rec = MsiCreateRecord(2);
2669     MsiRecordSetString(rec, 1, "One");
2670     MsiRecordSetString(rec, 2, "Two");
2671     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2672     r = run_query(hdb, rec, query);
2673     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2674     MsiCloseHandle(rec);
2675
2676     /* try table name as a marker */
2677     rec = MsiCreateRecord(1);
2678     MsiRecordSetString(rec, 1, "Table");
2679     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2680     r = run_query(hdb, rec, query);
2681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2682     MsiCloseHandle(rec);
2683
2684     /* try table name and values as markers */
2685     rec = MsiCreateRecord(3);
2686     MsiRecordSetString(rec, 1, "Table");
2687     MsiRecordSetInteger(rec, 2, 10);
2688     MsiRecordSetString(rec, 3, "haha");
2689     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2690     r = run_query(hdb, rec, query);
2691     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2692     MsiCloseHandle(rec);
2693
2694     /* try all markers */
2695     rec = MsiCreateRecord(5);
2696     MsiRecordSetString(rec, 1, "Table");
2697     MsiRecordSetString(rec, 1, "One");
2698     MsiRecordSetString(rec, 1, "Two");
2699     MsiRecordSetInteger(rec, 2, 10);
2700     MsiRecordSetString(rec, 3, "haha");
2701     query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2702     r = run_query(hdb, rec, query);
2703     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2704     MsiCloseHandle(rec);
2705
2706     /* insert an integer as a string */
2707     rec = MsiCreateRecord(2);
2708     MsiRecordSetString(rec, 1, "11");
2709     MsiRecordSetString(rec, 2, "hi");
2710     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2711     r = run_query(hdb, rec, query);
2712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2713     MsiCloseHandle(rec);
2714
2715     /* leave off the '' for the string */
2716     rec = MsiCreateRecord(2);
2717     MsiRecordSetInteger(rec, 1, 12);
2718     MsiRecordSetString(rec, 2, "hi");
2719     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2720     r = run_query(hdb, rec, query);
2721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2722     MsiCloseHandle(rec);
2723
2724     MsiCloseHandle(hdb);
2725     DeleteFileA(msifile);
2726 }
2727
2728 #define MY_NVIEWS 4000    /* Largest installer I've seen uses < 2k */
2729 static void test_handle_limit(void)
2730 {
2731     int i;
2732     MSIHANDLE hdb;
2733     MSIHANDLE hviews[MY_NVIEWS];
2734     UINT r;
2735
2736     /* create an empty db */
2737     hdb = create_db();
2738     ok( hdb, "failed to create db\n");
2739
2740     memset(hviews, 0, sizeof(hviews));
2741
2742     for (i=0; i<MY_NVIEWS; i++) {
2743         static char szQueryBuf[256] = "SELECT * from `_Tables`";
2744         hviews[i] = 0xdeadbeeb;
2745         r = MsiDatabaseOpenView(hdb, szQueryBuf, &hviews[i]);
2746         if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 
2747             hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2748             break;
2749     }
2750
2751     ok( i == MY_NVIEWS, "problem opening views\n");
2752
2753     for (i=0; i<MY_NVIEWS; i++) {
2754         if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2755             MsiViewClose(hviews[i]);
2756             r = MsiCloseHandle(hviews[i]);
2757             if (r != ERROR_SUCCESS)
2758                 break;
2759         }
2760     }
2761
2762     ok( i == MY_NVIEWS, "problem closing views\n");
2763
2764     r = MsiCloseHandle(hdb);
2765     ok( r == ERROR_SUCCESS, "failed to close database\n");
2766 }
2767
2768 static void generate_transform(void)
2769 {
2770     MSIHANDLE hdb1, hdb2, hrec;
2771     LPCSTR query;
2772     UINT r;
2773
2774     /* start with two identical databases */
2775     CopyFile(msifile2, msifile, FALSE);
2776
2777     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb1 );
2778     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2779
2780     r = MsiDatabaseCommit( hdb1 );
2781     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2782
2783     r = MsiOpenDatabase(msifile2, MSIDBOPEN_READONLY, &hdb2 );
2784     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2785
2786     /* the transform between two identical database should be empty */
2787     r = MsiDatabaseGenerateTransform(hdb1, hdb2, NULL, 0, 0);
2788     todo_wine {
2789     ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2790     }
2791
2792     query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2793     r = run_query(hdb1, 0, query);
2794     ok(r == ERROR_SUCCESS, "failed to add table\n");
2795
2796     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2797     r = run_query(hdb1, 0, query);
2798     ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2799
2800     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2801     r = run_query(hdb1, 0, query);
2802     ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2803
2804     query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2805     r = run_query(hdb1, 0, query);
2806     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2807
2808     query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2809     r = run_query(hdb1, 0, query);
2810     ok(r == ERROR_SUCCESS, "failed to delete row\n");
2811
2812     hrec = MsiCreateRecord(2);
2813     r = MsiRecordSetInteger(hrec, 1, 1);
2814     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2815
2816     write_file("testdata.bin", "naengmyon", 9);
2817     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
2818     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2819
2820     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2821     r = run_query(hdb1, hrec, query);
2822     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2823
2824     MsiCloseHandle(hrec);
2825
2826     query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2827     r = run_query(hdb1, 0, query);
2828     ok(r == ERROR_SUCCESS, "failed to add column\n");
2829
2830     query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2831     r = run_query(hdb1, 0, query);
2832     ok(r == ERROR_SUCCESS, "failed to add column\n");
2833
2834     query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2835     r = run_query(hdb1, 0, query);
2836     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2837
2838     query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2839             "`Value` CHAR(0) PRIMARY KEY `Property`)";
2840     r = run_query(hdb1, 0, query);
2841     ok(r == ERROR_SUCCESS, "failed to add property table\n");
2842
2843     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2844     r = run_query(hdb1, 0, query);
2845     ok(r == ERROR_SUCCESS, "failed to add property\n");
2846
2847     /* database needs to be committed */
2848     MsiDatabaseCommit(hdb1);
2849
2850     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2851     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2852
2853     MsiCloseHandle( hdb1 );
2854     MsiCloseHandle( hdb2 );
2855
2856     DeleteFile("testdata.bin");
2857 }
2858
2859 /* data for generating a transform */
2860
2861 /* tables transform names - encoded as they would be in an msi database file */
2862 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2863 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2864 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2865 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2866 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2867 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2868 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2869 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2870 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2871
2872 /* data in each table */
2873 static const WCHAR data1[] = { /* AAR */
2874     0x0201, 0x0008, 0x8001,  /* 0x0201 = add row (1), two shorts */
2875     0x0201, 0x0009, 0x8002,
2876 };
2877 static const WCHAR data2[] = { /* _Columns */
2878     0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2879     0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2880     0x0401, 0x0005, 0x0000, 0x0006, 0xbdff,  /* 0x0401 = add row (1), 4 shorts */
2881     0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2882     0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2883     0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2884 };
2885 static const WCHAR data3[] = { /* _Tables */
2886     0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2887     0x0101, 0x000a,
2888 };
2889 static const char data4[] = /* _StringData */
2890     "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval";  /* all the strings squashed together */
2891 static const WCHAR data5[] = { /* _StringPool */
2892 /*  len, refs */
2893     0,   0,    /* string 0 ''    */
2894     3,   2,    /* string 1 'MOO' */
2895     3,   1,    /* string 2 'COW' */
2896     3,   1,    /* string 3 'PIG' */
2897     1,   1,    /* string 4 'c'   */
2898     3,   3,    /* string 5 'AAR' */
2899     3,   1,    /* string 6 'CAR' */
2900     3,   1,    /* string 7 'BAR' */
2901     2,   1,    /* string 8 'vw'  */
2902     3,   1,    /* string 9 'bmw' */
2903     8,   4,    /* string 10 'Property' */
2904     5,   1,    /* string 11 'Value' */
2905     4,   1,    /* string 12 'prop' */
2906     3,   1,    /* string 13 'val' */
2907 };
2908 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2909 static const WCHAR data6[] = { /* MOO */
2910     0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2911     0x0000, 0x8003,         /* delete row */
2912 };
2913
2914 static const WCHAR data7[] = { /* BINARY */
2915     0x0201, 0x8001, 0x0001,
2916 };
2917
2918 static const char data8[] =  /* stream data for the BINARY table */
2919     "naengmyon";
2920
2921 static const WCHAR data9[] = { /* Property */
2922     0x0201, 0x000c, 0x000d,
2923 };
2924
2925 static const struct {
2926     LPCWSTR name;
2927     const void *data;
2928     DWORD size;
2929 } table_transform_data[] =
2930 {
2931     { name1, data1, sizeof data1 },
2932     { name2, data2, sizeof data2 },
2933     { name3, data3, sizeof data3 },
2934     { name4, data4, sizeof data4 - 1 },
2935     { name5, data5, sizeof data5 },
2936     { name6, data6, sizeof data6 },
2937     { name7, data7, sizeof data7 },
2938     { name8, data8, sizeof data8 - 1 },
2939     { name9, data9, sizeof data9 },
2940 };
2941
2942 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2943
2944 static void generate_transform_manual(void)
2945 {
2946     IStorage *stg = NULL;
2947     IStream *stm;
2948     WCHAR name[0x20];
2949     HRESULT r;
2950     DWORD i, count;
2951     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2952
2953     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2954
2955     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2956
2957     r = StgCreateDocfile(name, mode, 0, &stg);
2958     ok(r == S_OK, "failed to create storage\n");
2959     if (!stg)
2960         return;
2961
2962     r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2963     ok(r == S_OK, "failed to set storage type\n");
2964
2965     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2966     {
2967         r = IStorage_CreateStream( stg, table_transform_data[i].name,
2968                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2969         if (FAILED(r))
2970         {
2971             ok(0, "failed to create stream %08x\n", r);
2972             continue;
2973         }
2974
2975         r = IStream_Write( stm, table_transform_data[i].data,
2976                           table_transform_data[i].size, &count );
2977         if (FAILED(r) || count != table_transform_data[i].size)
2978             ok(0, "failed to write stream\n");
2979         IStream_Release(stm);
2980     }
2981
2982     IStorage_Release(stg);
2983 }
2984
2985 static UINT set_summary_info(MSIHANDLE hdb)
2986 {
2987     UINT res;
2988     MSIHANDLE suminfo;
2989
2990     /* build summary info */
2991     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
2992     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2993
2994     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
2995                         "Installation Database");
2996     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2997
2998     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
2999                         "Installation Database");
3000     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3001
3002     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
3003                         "Wine Hackers");
3004     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3005
3006     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
3007                     ";1033,2057");
3008     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3009
3010     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
3011                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
3012     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3013
3014     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
3015     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3016
3017     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
3018     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3019
3020     res = MsiSummaryInfoPersist(suminfo);
3021     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
3022
3023     res = MsiCloseHandle( suminfo);
3024     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
3025
3026     return res;
3027 }
3028
3029 static MSIHANDLE create_package_db(LPCSTR filename)
3030 {
3031     MSIHANDLE hdb = 0;
3032     UINT res;
3033
3034     DeleteFile(msifile);
3035
3036     /* create an empty database */
3037     res = MsiOpenDatabase(filename, MSIDBOPEN_CREATE, &hdb );
3038     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
3039     if( res != ERROR_SUCCESS )
3040         return hdb;
3041
3042     res = MsiDatabaseCommit( hdb );
3043     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
3044
3045     res = set_summary_info(hdb);
3046     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3047
3048     res = create_directory_table(hdb);
3049     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
3050
3051     return hdb;
3052 }
3053
3054 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
3055 {
3056     UINT res;
3057     CHAR szPackage[12];
3058     MSIHANDLE hPackage;
3059
3060     sprintf(szPackage, "#%u", hdb);
3061     res = MsiOpenPackage(szPackage, &hPackage);
3062     if (res != ERROR_SUCCESS)
3063         return res;
3064
3065     res = MsiCloseHandle(hdb);
3066     if (res != ERROR_SUCCESS)
3067     {
3068         MsiCloseHandle(hPackage);
3069         return res;
3070     }
3071
3072     *handle = hPackage;
3073     return ERROR_SUCCESS;
3074 }
3075
3076 static void test_try_transform(void)
3077 {
3078     MSIHANDLE hdb, hview, hrec, hpkg = 0;
3079     LPCSTR query;
3080     UINT r;
3081     DWORD sz;
3082     char buffer[MAX_PATH];
3083
3084     DeleteFile(msifile);
3085     DeleteFile(mstfile);
3086
3087     /* create the database */
3088     hdb = create_package_db(msifile);
3089     ok(hdb, "Failed to create package db\n");
3090
3091     query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
3092     r = run_query(hdb, 0, query);
3093     ok(r == ERROR_SUCCESS, "failed to add table\n");
3094
3095     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
3096     r = run_query(hdb, 0, query);
3097     ok(r == ERROR_SUCCESS, "failed to add row\n");
3098
3099     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
3100     r = run_query(hdb, 0, query);
3101     ok(r == ERROR_SUCCESS, "failed to add row\n");
3102
3103     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
3104     r = run_query(hdb, 0, query);
3105     ok(r == ERROR_SUCCESS, "failed to add row\n");
3106
3107     query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
3108     r = run_query(hdb, 0, query);
3109     ok(r == ERROR_SUCCESS, "failed to add table\n");
3110
3111     hrec = MsiCreateRecord(2);
3112     r = MsiRecordSetInteger(hrec, 1, 2);
3113     ok(r == ERROR_SUCCESS, "failed to set integer\n");
3114
3115     write_file("testdata.bin", "lamyon", 6);
3116     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
3117     ok(r == ERROR_SUCCESS, "failed to set stream\n");
3118
3119     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3120     r = run_query(hdb, hrec, query);
3121     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3122
3123     MsiCloseHandle(hrec);
3124
3125     r = MsiDatabaseCommit( hdb );
3126     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3127
3128     MsiCloseHandle( hdb );
3129     DeleteFileA("testdata.bin");
3130
3131     /*
3132      * Both these generate an equivalent transform,
3133      *  but the first doesn't work in Wine yet
3134      *  because MsiDatabaseGenerateTransform is unimplemented.
3135      */
3136     if (0)
3137         generate_transform();
3138     else
3139         generate_transform_manual();
3140
3141     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb );
3142     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3143
3144     r = MsiDatabaseApplyTransform( hdb, mstfile, 0 );
3145     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3146
3147     MsiDatabaseCommit( hdb );
3148
3149     /* check new values */
3150     hrec = 0;
3151     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3152     r = do_query(hdb, query, &hrec);
3153     ok(r == ERROR_SUCCESS, "select query failed\n");
3154     MsiCloseHandle(hrec);
3155
3156     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3157     hrec = 0;
3158     r = do_query(hdb, query, &hrec);
3159     ok(r == ERROR_SUCCESS, "select query failed\n");
3160     MsiCloseHandle(hrec);
3161
3162     /* check updated values */
3163     hrec = 0;
3164     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3165     r = do_query(hdb, query, &hrec);
3166     ok(r == ERROR_SUCCESS, "select query failed\n");
3167     MsiCloseHandle(hrec);
3168
3169     /* check unchanged value */
3170     hrec = 0;
3171     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3172     r = do_query(hdb, query, &hrec);
3173     ok(r == ERROR_SUCCESS, "select query failed\n");
3174     MsiCloseHandle(hrec);
3175
3176     /* check deleted value */
3177     hrec = 0;
3178     query = "select * from `MOO` where `NOO` = 3";
3179     r = do_query(hdb, query, &hrec);
3180     ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3181     if (hrec) MsiCloseHandle(hrec);
3182
3183     /* check added stream */
3184     hrec = 0;
3185     query = "select `BLOB` from `BINARY` where `ID` = 1";
3186     r = do_query(hdb, query, &hrec);
3187     ok(r == ERROR_SUCCESS, "select query failed\n");
3188
3189     /* check the contents of the stream */
3190     sz = sizeof buffer;
3191     r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3192     ok(r == ERROR_SUCCESS, "read stream failed\n");
3193     ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3194     ok(sz == 9, "stream data was wrong size\n");
3195     if (hrec) MsiCloseHandle(hrec);
3196
3197     /* check the validity of the table with a deleted row */
3198     hrec = 0;
3199     query = "select * from `MOO`";
3200     r = MsiDatabaseOpenView(hdb, query, &hview);
3201     ok(r == ERROR_SUCCESS, "open view failed\n");
3202
3203     r = MsiViewExecute(hview, 0);
3204     ok(r == ERROR_SUCCESS, "view execute failed\n");
3205
3206     r = MsiViewFetch(hview, &hrec);
3207     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3208
3209     r = MsiRecordGetInteger(hrec, 1);
3210     ok(r == 1, "Expected 1, got %d\n", r);
3211
3212     sz = sizeof buffer;
3213     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3214     ok(r == ERROR_SUCCESS, "record get string failed\n");
3215     ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3216
3217     r = MsiRecordGetInteger(hrec, 3);
3218     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3219
3220     r = MsiRecordGetInteger(hrec, 4);
3221     ok(r == 5, "Expected 5, got %d\n", r);
3222
3223     MsiCloseHandle(hrec);
3224
3225     r = MsiViewFetch(hview, &hrec);
3226     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3227
3228     r = MsiRecordGetInteger(hrec, 1);
3229     ok(r == 2, "Expected 2, got %d\n", r);
3230
3231     sz = sizeof buffer;
3232     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3233     ok(r == ERROR_SUCCESS, "record get string failed\n");
3234     ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3235
3236     r = MsiRecordGetInteger(hrec, 3);
3237     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3238
3239     r = MsiRecordGetInteger(hrec, 4);
3240     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3241
3242     MsiCloseHandle(hrec);
3243
3244     r = MsiViewFetch(hview, &hrec);
3245     ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3246
3247     MsiCloseHandle(hrec);
3248     MsiViewClose(hview);
3249     MsiCloseHandle(hview);
3250
3251     /* check that the property was added */
3252     r = package_from_db(hdb, &hpkg);
3253     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3254     {
3255         skip("Not enough rights to perform tests\n");
3256         goto error;
3257     }
3258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3259
3260     sz = MAX_PATH;
3261     r = MsiGetProperty(hpkg, "prop", buffer, &sz);
3262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3263     ok(!lstrcmp(buffer, "val"), "Expected val, got %s\n", buffer);
3264
3265     MsiCloseHandle(hpkg);
3266
3267 error:
3268     MsiCloseHandle(hdb);
3269     DeleteFile(msifile);
3270     DeleteFile(mstfile);
3271 }
3272
3273 struct join_res
3274 {
3275     const CHAR one[MAX_PATH];
3276     const CHAR two[MAX_PATH];
3277 };
3278
3279 struct join_res_4col
3280 {
3281     const CHAR one[MAX_PATH];
3282     const CHAR two[MAX_PATH];
3283     const CHAR three[MAX_PATH];
3284     const CHAR four[MAX_PATH];
3285 };
3286
3287 struct join_res_uint
3288 {
3289     UINT one;
3290     UINT two;
3291     UINT three;
3292     UINT four;
3293     UINT five;
3294     UINT six;
3295 };
3296
3297 static const struct join_res join_res_first[] =
3298 {
3299     { "alveolar", "procerus" },
3300     { "septum", "procerus" },
3301     { "septum", "nasalis" },
3302     { "ramus", "nasalis" },
3303     { "malar", "mentalis" },
3304 };
3305
3306 static const struct join_res join_res_second[] =
3307 {
3308     { "nasal", "septum" },
3309     { "mandible", "ramus" },
3310 };
3311
3312 static const struct join_res join_res_third[] =
3313 {
3314     { "msvcp.dll", "abcdefgh" },
3315     { "msvcr.dll", "ijklmnop" },
3316 };
3317
3318 static const struct join_res join_res_fourth[] =
3319 {
3320     { "msvcp.dll.01234", "single.dll.31415" },
3321 };
3322
3323 static const struct join_res join_res_fifth[] =
3324 {
3325     { "malar", "procerus" },
3326 };
3327
3328 static const struct join_res join_res_sixth[] =
3329 {
3330     { "malar", "procerus" },
3331     { "malar", "procerus" },
3332     { "malar", "nasalis" },
3333     { "malar", "nasalis" },
3334     { "malar", "nasalis" },
3335     { "malar", "mentalis" },
3336 };
3337
3338 static const struct join_res join_res_seventh[] =
3339 {
3340     { "malar", "nasalis" },
3341     { "malar", "nasalis" },
3342     { "malar", "nasalis" },
3343 };
3344
3345 static const struct join_res_4col join_res_eighth[] =
3346 {
3347     { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3348     { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3349     { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3350     { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3351     { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3352     { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3353 };
3354
3355 static const struct join_res_uint join_res_ninth[] =
3356 {
3357     { 1, 2, 3, 4, 7, 8 },
3358     { 1, 2, 5, 6, 7, 8 },
3359     { 1, 2, 3, 4, 9, 10 },
3360     { 1, 2, 5, 6, 9, 10 },
3361     { 1, 2, 3, 4, 11, 12 },
3362     { 1, 2, 5, 6, 11, 12 },
3363 };
3364
3365 static void test_join(void)
3366 {
3367     MSIHANDLE hdb, hview, hrec;
3368     LPCSTR query;
3369     CHAR buf[MAX_PATH];
3370     UINT r, count;
3371     DWORD size, i;
3372     BOOL data_correct;
3373
3374     hdb = create_db();
3375     ok( hdb, "failed to create db\n");
3376
3377     r = create_component_table( hdb );
3378     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3379
3380     r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3381     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3382
3383     r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3384     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3385
3386     r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3387     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3388
3389     r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3390     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3391
3392     r = create_feature_components_table( hdb );
3393     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3394
3395     r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3396     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3397
3398     r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3399     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3400
3401     r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3402     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3403
3404     r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3405     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3406
3407     r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3408     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3409
3410     r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3411     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3412
3413     r = create_std_dlls_table( hdb );
3414     ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3415
3416     r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3417     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3418
3419     r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3420     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3421
3422     r = create_binary_table( hdb );
3423     ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3424
3425     r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3426     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3427
3428     r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3429     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3430
3431     r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3432     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3433
3434     query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3435     r = run_query( hdb, 0, query);
3436     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3437
3438     query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3439     r = run_query( hdb, 0, query);
3440     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3441
3442     query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3443     r = run_query( hdb, 0, query);
3444     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3445
3446     query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3447     r = run_query( hdb, 0, query);
3448     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3449
3450     query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3451     r = run_query( hdb, 0, query);
3452     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3453
3454     query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3455     r = run_query( hdb, 0, query);
3456     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3457
3458     query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3459     r = run_query( hdb, 0, query);
3460     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3461
3462     query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3463     r = run_query( hdb, 0, query);
3464     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3465
3466     query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3467     r = run_query( hdb, 0, query);
3468     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3469
3470     query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3471     r = run_query( hdb, 0, query);
3472     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3473
3474     query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3475     r = run_query( hdb, 0, query);
3476     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3477
3478     query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3479     r = run_query( hdb, 0, query);
3480     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3481
3482     query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3483     r = run_query( hdb, 0, query);
3484     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3485
3486     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3487             "FROM `Component`, `FeatureComponents` "
3488             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3489             "ORDER BY `Feature_`";
3490     r = MsiDatabaseOpenView(hdb, query, &hview);
3491     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3492
3493     r = MsiViewExecute(hview, 0);
3494     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3495
3496     i = 0;
3497     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3498     {
3499         count = MsiRecordGetFieldCount( hrec );
3500         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3501
3502         size = MAX_PATH;
3503         r = MsiRecordGetString( hrec, 1, buf, &size );
3504         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3505         ok( !lstrcmp( buf, join_res_first[i].one ),
3506             "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3507
3508         size = MAX_PATH;
3509         r = MsiRecordGetString( hrec, 2, buf, &size );
3510         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3511         ok( !lstrcmp( buf, join_res_first[i].two ),
3512             "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3513
3514         i++;
3515         MsiCloseHandle(hrec);
3516     }
3517
3518     ok( i == 5, "Expected 5 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     /* try a join without a WHERE condition */
3525     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3526             "FROM `Component`, `FeatureComponents` ";
3527     r = MsiDatabaseOpenView(hdb, query, &hview);
3528     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3529
3530     r = MsiViewExecute(hview, 0);
3531     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3532
3533     i = 0;
3534     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3535     {
3536         i++;
3537         MsiCloseHandle(hrec);
3538     }
3539     ok( i == 24, "Expected 24 rows, got %d\n", i );
3540
3541     MsiViewClose(hview);
3542     MsiCloseHandle(hview);
3543
3544     query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3545             "WHERE FeatureComponents.Component_=Component.Component "
3546             "AND (Feature_='nasalis') ORDER BY Feature_";
3547     r = MsiDatabaseOpenView(hdb, query, &hview);
3548     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3549
3550     r = MsiViewExecute(hview, 0);
3551     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3552
3553     i = 0;
3554     data_correct = TRUE;
3555     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3556     {
3557         count = MsiRecordGetFieldCount( hrec );
3558         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3559
3560         size = MAX_PATH;
3561         r = MsiRecordGetString( hrec, 1, buf, &size );
3562         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3563         if( lstrcmp( buf, join_res_second[i].one ))
3564             data_correct = FALSE;
3565
3566         size = MAX_PATH;
3567         r = MsiRecordGetString( hrec, 2, buf, &size );
3568         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3569         if( lstrcmp( buf, join_res_second[i].two ))
3570             data_correct = FALSE;
3571
3572         i++;
3573         MsiCloseHandle(hrec);
3574     }
3575
3576     ok( data_correct, "data returned in the wrong order\n");
3577
3578     ok( i == 2, "Expected 2 rows, got %d\n", i );
3579     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3580
3581     MsiViewClose(hview);
3582     MsiCloseHandle(hview);
3583
3584     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3585             "FROM `StdDlls`, `Binary` "
3586             "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3587             "ORDER BY `File`";
3588     r = MsiDatabaseOpenView(hdb, query, &hview);
3589     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3590
3591     r = MsiViewExecute(hview, 0);
3592     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3593
3594     i = 0;
3595     data_correct = TRUE;
3596     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3597     {
3598         count = MsiRecordGetFieldCount( hrec );
3599         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3600
3601         size = MAX_PATH;
3602         r = MsiRecordGetString( hrec, 1, buf, &size );
3603         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3604         if( lstrcmp( buf, join_res_third[i].one ) )
3605             data_correct = FALSE;
3606
3607         size = MAX_PATH;
3608         r = MsiRecordGetString( hrec, 2, buf, &size );
3609         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3610         if( lstrcmp( buf, join_res_third[i].two ) )
3611             data_correct = FALSE;
3612
3613         i++;
3614         MsiCloseHandle(hrec);
3615     }
3616     ok( data_correct, "data returned in the wrong order\n");
3617
3618     ok( i == 2, "Expected 2 rows, got %d\n", i );
3619
3620     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3621
3622     MsiViewClose(hview);
3623     MsiCloseHandle(hview);
3624
3625     query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3626             "FROM `StdDlls`, `Binary` "
3627             "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3628             "ORDER BY `Name`";
3629     r = MsiDatabaseOpenView(hdb, query, &hview);
3630     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3631
3632     r = MsiViewExecute(hview, 0);
3633     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3634
3635     i = 0;
3636     data_correct = TRUE;
3637     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3638     {
3639         count = MsiRecordGetFieldCount( hrec );
3640         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3641
3642         size = MAX_PATH;
3643         r = MsiRecordGetString( hrec, 1, buf, &size );
3644         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3645         if( lstrcmp( buf, join_res_fourth[i].one ))
3646             data_correct = FALSE;
3647
3648         size = MAX_PATH;
3649         r = MsiRecordGetString( hrec, 2, buf, &size );
3650         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3651         if( lstrcmp( buf, join_res_fourth[i].two ))
3652             data_correct = FALSE;
3653
3654         i++;
3655         MsiCloseHandle(hrec);
3656     }
3657     ok( data_correct, "data returned in the wrong order\n");
3658
3659     ok( i == 1, "Expected 1 rows, got %d\n", i );
3660     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3661
3662     MsiViewClose(hview);
3663     MsiCloseHandle(hview);
3664
3665     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3666             "FROM `Component`, `FeatureComponents` "
3667             "WHERE `Component`.`Component` = 'zygomatic' "
3668             "AND `FeatureComponents`.`Component_` = 'maxilla' "
3669             "ORDER BY `Feature_`";
3670     r = MsiDatabaseOpenView(hdb, query, &hview);
3671     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3672
3673     r = MsiViewExecute(hview, 0);
3674     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3675
3676     i = 0;
3677     data_correct = TRUE;
3678     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3679     {
3680         count = MsiRecordGetFieldCount( hrec );
3681         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3682
3683         size = MAX_PATH;
3684         r = MsiRecordGetString( hrec, 1, buf, &size );
3685         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3686         if( lstrcmp( buf, join_res_fifth[i].one ))
3687             data_correct = FALSE;
3688
3689         size = MAX_PATH;
3690         r = MsiRecordGetString( hrec, 2, buf, &size );
3691         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3692         if( lstrcmp( buf, join_res_fifth[i].two ))
3693             data_correct = FALSE;
3694
3695         i++;
3696         MsiCloseHandle(hrec);
3697     }
3698     ok( data_correct, "data returned in the wrong order\n");
3699
3700     ok( i == 1, "Expected 1 rows, got %d\n", i );
3701     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3702
3703     MsiViewClose(hview);
3704     MsiCloseHandle(hview);
3705
3706     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3707             "FROM `Component`, `FeatureComponents` "
3708             "WHERE `Component` = 'zygomatic' "
3709             "ORDER BY `Feature_`";
3710     r = MsiDatabaseOpenView(hdb, query, &hview);
3711     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3712
3713     r = MsiViewExecute(hview, 0);
3714     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3715
3716     i = 0;
3717     data_correct = TRUE;
3718     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3719     {
3720         count = MsiRecordGetFieldCount( hrec );
3721         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3722
3723         size = MAX_PATH;
3724         r = MsiRecordGetString( hrec, 1, buf, &size );
3725         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3726         if( lstrcmp( buf, join_res_sixth[i].one ))
3727             data_correct = FALSE;
3728
3729         size = MAX_PATH;
3730         r = MsiRecordGetString( hrec, 2, buf, &size );
3731         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3732         if( lstrcmp( buf, join_res_sixth[i].two ))
3733             data_correct = FALSE;
3734
3735         i++;
3736         MsiCloseHandle(hrec);
3737     }
3738     ok( data_correct, "data returned in the wrong order\n");
3739
3740     ok( i == 6, "Expected 6 rows, got %d\n", i );
3741     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3742
3743     MsiViewClose(hview);
3744     MsiCloseHandle(hview);
3745
3746     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3747             "FROM `Component`, `FeatureComponents` "
3748             "WHERE `Component` = 'zygomatic' "
3749             "AND `Feature_` = 'nasalis' "
3750             "ORDER BY `Feature_`";
3751     r = MsiDatabaseOpenView(hdb, query, &hview);
3752     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3753
3754     r = MsiViewExecute(hview, 0);
3755     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3756
3757     i = 0;
3758     data_correct = TRUE;
3759     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3760     {
3761         count = MsiRecordGetFieldCount( hrec );
3762         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3763
3764         size = MAX_PATH;
3765         r = MsiRecordGetString( hrec, 1, buf, &size );
3766         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3767         if( lstrcmp( buf, join_res_seventh[i].one ))
3768             data_correct = FALSE;
3769
3770         size = MAX_PATH;
3771         r = MsiRecordGetString( hrec, 2, buf, &size );
3772         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3773         if( lstrcmp( buf, join_res_seventh[i].two ))
3774             data_correct = FALSE;
3775
3776         i++;
3777         MsiCloseHandle(hrec);
3778     }
3779
3780     ok( data_correct, "data returned in the wrong order\n");
3781     ok( i == 3, "Expected 3 rows, got %d\n", i );
3782     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3783
3784     MsiViewClose(hview);
3785     MsiCloseHandle(hview);
3786
3787     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3788             "FROM `StdDlls`, `Binary` ";
3789     r = MsiDatabaseOpenView(hdb, query, &hview);
3790     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3791
3792     r = MsiViewExecute(hview, 0);
3793     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3794
3795     i = 0;
3796     data_correct = TRUE;
3797     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3798     {
3799         count = MsiRecordGetFieldCount( hrec );
3800         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3801
3802         size = MAX_PATH;
3803         r = MsiRecordGetString( hrec, 1, buf, &size );
3804         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3805         if( lstrcmp( buf, join_res_eighth[i].one ))
3806             data_correct = FALSE;
3807
3808         size = MAX_PATH;
3809         r = MsiRecordGetString( hrec, 2, buf, &size );
3810         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3811         if( lstrcmp( buf, join_res_eighth[i].four ))
3812             data_correct = FALSE;
3813
3814         i++;
3815         MsiCloseHandle(hrec);
3816     }
3817
3818     ok( data_correct, "data returned in the wrong order\n");
3819     ok( i == 6, "Expected 6 rows, got %d\n", i );
3820     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3821
3822     MsiViewClose(hview);
3823     MsiCloseHandle(hview);
3824
3825     query = "SELECT * FROM `StdDlls`, `Binary` ";
3826     r = MsiDatabaseOpenView(hdb, query, &hview);
3827     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3828
3829     r = MsiViewExecute(hview, 0);
3830     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3831
3832     i = 0;
3833     data_correct = TRUE;
3834     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3835     {
3836         count = MsiRecordGetFieldCount( hrec );
3837         ok( count == 4, "Expected 4 record fields, got %d\n", count );
3838
3839         size = MAX_PATH;
3840         r = MsiRecordGetString( hrec, 1, buf, &size );
3841         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3842         if( lstrcmp( buf, join_res_eighth[i].one ))
3843             data_correct = FALSE;
3844
3845         size = MAX_PATH;
3846         r = MsiRecordGetString( hrec, 2, buf, &size );
3847         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3848         if( lstrcmp( buf, join_res_eighth[i].two ))
3849             data_correct = FALSE;
3850
3851         size = MAX_PATH;
3852         r = MsiRecordGetString( hrec, 3, buf, &size );
3853         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3854         if( lstrcmp( buf, join_res_eighth[i].three ))
3855             data_correct = FALSE;
3856
3857         size = MAX_PATH;
3858         r = MsiRecordGetString( hrec, 4, buf, &size );
3859         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3860         if( lstrcmp( buf, join_res_eighth[i].four ))
3861             data_correct = FALSE;
3862
3863         i++;
3864         MsiCloseHandle(hrec);
3865     }
3866     ok( data_correct, "data returned in the wrong order\n");
3867
3868     ok( i == 6, "Expected 6 rows, got %d\n", i );
3869     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3870
3871     MsiViewClose(hview);
3872     MsiCloseHandle(hview);
3873
3874     query = "SELECT * FROM `One`, `Two`, `Three` ";
3875     r = MsiDatabaseOpenView(hdb, query, &hview);
3876     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3877
3878     r = MsiViewExecute(hview, 0);
3879     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3880
3881     i = 0;
3882     data_correct = TRUE;
3883     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3884     {
3885         count = MsiRecordGetFieldCount( hrec );
3886         ok( count == 6, "Expected 6 record fields, got %d\n", count );
3887
3888         r = MsiRecordGetInteger( hrec, 1 );
3889         if( r != join_res_ninth[i].one )
3890             data_correct = FALSE;
3891
3892         r = MsiRecordGetInteger( hrec, 2 );
3893         if( r != join_res_ninth[i].two )
3894             data_correct = FALSE;
3895
3896         r = MsiRecordGetInteger( hrec, 3 );
3897         if( r != join_res_ninth[i].three )
3898             data_correct = FALSE;
3899
3900         r = MsiRecordGetInteger( hrec, 4 );
3901         if( r != join_res_ninth[i].four )
3902             data_correct = FALSE;
3903
3904         r = MsiRecordGetInteger( hrec, 5 );
3905         if( r != join_res_ninth[i].five )
3906             data_correct = FALSE;
3907
3908         r = MsiRecordGetInteger( hrec, 6);
3909         if( r != join_res_ninth[i].six )
3910             data_correct = FALSE;
3911
3912         i++;
3913         MsiCloseHandle(hrec);
3914     }
3915     ok( data_correct, "data returned in the wrong order\n");
3916
3917     ok( i == 6, "Expected 6 rows, got %d\n", i );
3918     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3919
3920     MsiViewClose(hview);
3921     MsiCloseHandle(hview);
3922
3923     query = "SELECT * FROM `Four`, `Five`";
3924     r = MsiDatabaseOpenView(hdb, query, &hview);
3925     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3926
3927     r = MsiViewExecute(hview, 0);
3928     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3929
3930     r = MsiViewFetch(hview, &hrec);
3931     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3932
3933     MsiViewClose(hview);
3934     MsiCloseHandle(hview);
3935
3936     query = "SELECT * FROM `Nonexistent`, `One`";
3937     r = MsiDatabaseOpenView(hdb, query, &hview);
3938     ok( r == ERROR_BAD_QUERY_SYNTAX,
3939         "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3940
3941     /* try updating a row in a join table */
3942     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3943             "FROM `Component`, `FeatureComponents` "
3944             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3945             "ORDER BY `Feature_`";
3946     r = MsiDatabaseOpenView(hdb, query, &hview);
3947     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3948
3949     r = MsiViewExecute(hview, 0);
3950     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3951
3952     r = MsiViewFetch(hview, &hrec);
3953     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3954
3955     r = MsiRecordSetString( hrec, 1, "epicranius" );
3956     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3957
3958     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3959     ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3960
3961     /* try another valid operation for joins */
3962     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3963     todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3964
3965     /* try an invalid operation for joins */
3966     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3967     ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3968
3969     r = MsiRecordSetString( hrec, 2, "epicranius" );
3970     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3971
3972     /* primary key cannot be updated */
3973     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3974     ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3975
3976     MsiCloseHandle(hrec);
3977     MsiViewClose(hview);
3978     MsiCloseHandle(hview);
3979
3980     r = MsiDatabaseOpenView(hdb, query, &hview);
3981     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3982
3983     r = MsiViewExecute(hview, 0);
3984     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3985
3986     r = MsiViewFetch(hview, &hrec);
3987     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3988
3989     size = MAX_PATH;
3990     r = MsiRecordGetString( hrec, 1, buf, &size );
3991     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3992     ok( !lstrcmp( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
3993
3994     MsiCloseHandle(hrec);
3995     MsiViewClose(hview);
3996     MsiCloseHandle(hview);
3997
3998     MsiCloseHandle(hdb);
3999     DeleteFile(msifile);
4000 }
4001
4002 static void test_temporary_table(void)
4003 {
4004     MSICONDITION cond;
4005     MSIHANDLE hdb = 0, view = 0, rec;
4006     const char *query;
4007     UINT r;
4008     char buf[0x10];
4009     DWORD sz;
4010
4011     cond = MsiDatabaseIsTablePersistent(0, NULL);
4012     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
4013
4014     hdb = create_db();
4015     ok( hdb, "failed to create db\n");
4016
4017     cond = MsiDatabaseIsTablePersistent(hdb, NULL);
4018     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
4019
4020     cond = MsiDatabaseIsTablePersistent(hdb, "_Tables");
4021     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4022
4023     cond = MsiDatabaseIsTablePersistent(hdb, "_Columns");
4024     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4025
4026     cond = MsiDatabaseIsTablePersistent(hdb, "_Storages");
4027     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4028
4029     cond = MsiDatabaseIsTablePersistent(hdb, "_Streams");
4030     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4031
4032     query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
4033     r = run_query(hdb, 0, query);
4034     ok(r == ERROR_SUCCESS, "failed to add table\n");
4035
4036     cond = MsiDatabaseIsTablePersistent(hdb, "P");
4037     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4038
4039     query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
4040     r = run_query(hdb, 0, query);
4041     ok(r == ERROR_SUCCESS, "failed to add table\n");
4042
4043     cond = MsiDatabaseIsTablePersistent(hdb, "P2");
4044     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4045
4046     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4047     r = run_query(hdb, 0, query);
4048     ok(r == ERROR_SUCCESS, "failed to add table\n");
4049
4050     cond = MsiDatabaseIsTablePersistent(hdb, "T");
4051     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4052
4053     query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4054     r = run_query(hdb, 0, query);
4055     ok(r == ERROR_SUCCESS, "failed to add table\n");
4056
4057     query = "SELECT * FROM `T2`";
4058     r = MsiDatabaseOpenView(hdb, query, &view);
4059     ok(r == ERROR_BAD_QUERY_SYNTAX,
4060        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4061
4062     cond = MsiDatabaseIsTablePersistent(hdb, "T2");
4063     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4064
4065     query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
4066     r = run_query(hdb, 0, query);
4067     ok(r == ERROR_SUCCESS, "failed to add table\n");
4068
4069     cond = MsiDatabaseIsTablePersistent(hdb, "T3");
4070     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4071
4072     query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4073     r = run_query(hdb, 0, query);
4074     ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
4075
4076     cond = MsiDatabaseIsTablePersistent(hdb, "T4");
4077     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4078
4079     query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
4080     r = run_query(hdb, 0, query);
4081     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
4082
4083     query = "select * from `T`";
4084     r = MsiDatabaseOpenView(hdb, query, &view);
4085     ok(r == ERROR_SUCCESS, "failed to query table\n");
4086     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4087     ok(r == ERROR_SUCCESS, "failed to get column info\n");
4088
4089     sz = sizeof buf;
4090     r = MsiRecordGetString(rec, 1, buf, &sz);
4091     ok(r == ERROR_SUCCESS, "failed to get string\n");
4092     ok( 0 == strcmp("G255", buf), "wrong column type\n");
4093
4094     sz = sizeof buf;
4095     r = MsiRecordGetString(rec, 2, buf, &sz);
4096     ok(r == ERROR_SUCCESS, "failed to get string\n");
4097     ok( 0 == strcmp("j2", buf), "wrong column type\n");
4098
4099     MsiCloseHandle( rec );
4100     MsiViewClose( view );
4101     MsiCloseHandle( view );
4102
4103     /* query the table data */
4104     rec = 0;
4105     r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
4106     ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
4107     MsiCloseHandle( rec );
4108
4109     /* query the column data */
4110     rec = 0;
4111     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
4112     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4113     if (rec) MsiCloseHandle( rec );
4114
4115     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
4116     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4117     if (rec) MsiCloseHandle( rec );
4118
4119     MsiCloseHandle( hdb );
4120
4121     DeleteFile(msifile);
4122 }
4123
4124 static void test_alter(void)
4125 {
4126     MSICONDITION cond;
4127     MSIHANDLE hdb = 0;
4128     const char *query;
4129     UINT r;
4130
4131     hdb = create_db();
4132     ok( hdb, "failed to create db\n");
4133
4134     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4135     r = run_query(hdb, 0, query);
4136     ok(r == ERROR_SUCCESS, "failed to add table\n");
4137
4138     cond = MsiDatabaseIsTablePersistent(hdb, "T");
4139     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4140
4141     query = "ALTER TABLE `T` HOLD";
4142     r = run_query(hdb, 0, query);
4143     ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4144
4145     query = "ALTER TABLE `T` FREE";
4146     r = run_query(hdb, 0, query);
4147     ok(r == ERROR_SUCCESS, "failed to free table\n");
4148
4149     query = "ALTER TABLE `T` FREE";
4150     r = run_query(hdb, 0, query);
4151     ok(r == ERROR_SUCCESS, "failed to free table\n");
4152
4153     query = "ALTER TABLE `T` FREE";
4154     r = run_query(hdb, 0, query);
4155     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4156
4157     query = "ALTER TABLE `T` HOLD";
4158     r = run_query(hdb, 0, query);
4159     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4160
4161     /* table T is removed */
4162     query = "SELECT * FROM `T`";
4163     r = run_query(hdb, 0, query);
4164     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4165
4166     /* create the table again */
4167     query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4168     r = run_query(hdb, 0, query);
4169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4170
4171     /* up the ref count */
4172     query = "ALTER TABLE `U` HOLD";
4173     r = run_query(hdb, 0, query);
4174     ok(r == ERROR_SUCCESS, "failed to free table\n");
4175
4176     /* add column, no data type */
4177     query = "ALTER TABLE `U` ADD `C`";
4178     r = run_query(hdb, 0, query);
4179     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4180
4181     query = "ALTER TABLE `U` ADD `C` INTEGER";
4182     r = run_query(hdb, 0, query);
4183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4184
4185     /* add column C again */
4186     query = "ALTER TABLE `U` ADD `C` INTEGER";
4187     r = run_query(hdb, 0, query);
4188     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4189
4190     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4191     r = run_query(hdb, 0, query);
4192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4193
4194     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4195     r = run_query(hdb, 0, query);
4196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4197
4198     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4199     r = run_query(hdb, 0, query);
4200     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4201
4202     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4203     r = run_query(hdb, 0, query);
4204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4205
4206     query = "SELECT * FROM `U` WHERE `D` = 8";
4207     r = run_query(hdb, 0, query);
4208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4209
4210     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4211     r = run_query(hdb, 0, query);
4212     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4213
4214     query = "ALTER COLUMN `D` FREE";
4215     r = run_query(hdb, 0, query);
4216     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4217
4218     /* drop the ref count */
4219     query = "ALTER TABLE `U` FREE";
4220     r = run_query(hdb, 0, query);
4221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4222
4223     /* table is not empty */
4224     query = "SELECT * FROM `U`";
4225     r = run_query(hdb, 0, query);
4226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4227
4228     /* column D is removed */
4229     query = "SELECT * FROM `U` WHERE `D` = 8";
4230     r = run_query(hdb, 0, query);
4231     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4232
4233     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4234     r = run_query(hdb, 0, query);
4235     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4236
4237     /* add the column again */
4238     query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4239     r = run_query(hdb, 0, query);
4240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4241
4242     /* up the ref count */
4243     query = "ALTER TABLE `U` HOLD";
4244     r = run_query(hdb, 0, query);
4245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4246
4247     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4248     r = run_query(hdb, 0, query);
4249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4250
4251     query = "SELECT * FROM `U` WHERE `E` = 16";
4252     r = run_query(hdb, 0, query);
4253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4254
4255     /* drop the ref count */
4256     query = "ALTER TABLE `U` FREE";
4257     r = run_query(hdb, 0, query);
4258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4259
4260     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4261     r = run_query(hdb, 0, query);
4262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4263
4264     query = "SELECT * FROM `U` WHERE `E` = 20";
4265     r = run_query(hdb, 0, query);
4266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4267
4268     /* drop the ref count */
4269     query = "ALTER TABLE `U` FREE";
4270     r = run_query(hdb, 0, query);
4271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4272
4273     /* table still exists */
4274     query = "SELECT * FROM `U`";
4275     r = run_query(hdb, 0, query);
4276     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4277
4278     /* col E is removed */
4279     query = "SELECT * FROM `U` WHERE `E` = 20";
4280     r = run_query(hdb, 0, query);
4281     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4282
4283     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4284     r = run_query(hdb, 0, query);
4285     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4286
4287     /* drop the ref count once more */
4288     query = "ALTER TABLE `U` FREE";
4289     r = run_query(hdb, 0, query);
4290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4291
4292     /* table still exists */
4293     query = "SELECT * FROM `U`";
4294     r = run_query(hdb, 0, query);
4295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4296
4297     MsiCloseHandle( hdb );
4298     DeleteFile(msifile);
4299 }
4300
4301 static void test_integers(void)
4302 {
4303     MSIHANDLE hdb = 0, view = 0, rec = 0;
4304     DWORD count, i;
4305     const char *query;
4306     UINT r;
4307
4308     /* just MsiOpenDatabase should not create a file */
4309     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4310     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4311
4312     /* create a table */
4313     query = "CREATE TABLE `integers` ( "
4314             "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4315             "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4316             "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4317             "PRIMARY KEY `one`)";
4318     r = MsiDatabaseOpenView(hdb, query, &view);
4319     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4320     r = MsiViewExecute(view, 0);
4321     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4322     r = MsiViewClose(view);
4323     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4324     r = MsiCloseHandle(view);
4325     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4326
4327     query = "SELECT * FROM `integers`";
4328     r = MsiDatabaseOpenView(hdb, query, &view);
4329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4330
4331     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4333     count = MsiRecordGetFieldCount(rec);
4334     ok(count == 8, "Expected 8, got %d\n", count);
4335     ok(check_record(rec, 1, "one"), "Expected one\n");
4336     ok(check_record(rec, 2, "two"), "Expected two\n");
4337     ok(check_record(rec, 3, "three"), "Expected three\n");
4338     ok(check_record(rec, 4, "four"), "Expected four\n");
4339     ok(check_record(rec, 5, "five"), "Expected five\n");
4340     ok(check_record(rec, 6, "six"), "Expected six\n");
4341     ok(check_record(rec, 7, "seven"), "Expected seven\n");
4342     ok(check_record(rec, 8, "eight"), "Expected eight\n");
4343     MsiCloseHandle(rec);
4344
4345     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4347     count = MsiRecordGetFieldCount(rec);
4348     ok(count == 8, "Expected 8, got %d\n", count);
4349     ok(check_record(rec, 1, "I2"), "Expected I2\n");
4350     ok(check_record(rec, 2, "I2"), "Expected I2\n");
4351     ok(check_record(rec, 3, "I2"), "Expected I2\n");
4352     ok(check_record(rec, 4, "I4"), "Expected I4\n");
4353     ok(check_record(rec, 5, "i2"), "Expected i2\n");
4354     ok(check_record(rec, 6, "i2"), "Expected i2\n");
4355     ok(check_record(rec, 7, "i2"), "Expected i2\n");
4356     ok(check_record(rec, 8, "i4"), "Expected i4\n");
4357     MsiCloseHandle(rec);
4358
4359     MsiViewClose(view);
4360     MsiCloseHandle(view);
4361
4362     /* insert values into it, NULL where NOT NULL is specified */
4363     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4364         "VALUES('', '', '', '', '', '', '', '')";
4365     r = MsiDatabaseOpenView(hdb, query, &view);
4366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4367     r = MsiViewExecute(view, 0);
4368     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4369
4370     MsiViewClose(view);
4371     MsiCloseHandle(view);
4372
4373     query = "SELECT * FROM `integers`";
4374     r = do_query(hdb, query, &rec);
4375     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4376
4377     r = MsiRecordGetFieldCount(rec);
4378     ok(r == -1, "record count wrong: %d\n", r);
4379
4380     MsiCloseHandle(rec);
4381
4382     /* insert legitimate values into it */
4383     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4384         "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4385     r = MsiDatabaseOpenView(hdb, query, &view);
4386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4387     r = MsiViewExecute(view, 0);
4388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4389
4390     query = "SELECT * FROM `integers`";
4391     r = do_query(hdb, query, &rec);
4392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4393
4394     r = MsiRecordGetFieldCount(rec);
4395     ok(r == 8, "record count wrong: %d\n", r);
4396
4397     i = MsiRecordGetInteger(rec, 1);
4398     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4399     i = MsiRecordGetInteger(rec, 3);
4400     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4401     i = MsiRecordGetInteger(rec, 2);
4402     ok(i == 2, "Expected 2, got %d\n", i);
4403     i = MsiRecordGetInteger(rec, 4);
4404     ok(i == 4, "Expected 4, got %d\n", i);
4405     i = MsiRecordGetInteger(rec, 5);
4406     ok(i == 5, "Expected 5, got %d\n", i);
4407     i = MsiRecordGetInteger(rec, 6);
4408     ok(i == 6, "Expected 6, got %d\n", i);
4409     i = MsiRecordGetInteger(rec, 7);
4410     ok(i == 7, "Expected 7, got %d\n", i);
4411     i = MsiRecordGetInteger(rec, 8);
4412     ok(i == 8, "Expected 8, got %d\n", i);
4413
4414     MsiCloseHandle(rec);
4415     MsiViewClose(view);
4416     MsiCloseHandle(view);
4417
4418     r = MsiDatabaseCommit(hdb);
4419     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4420
4421     r = MsiCloseHandle(hdb);
4422     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4423
4424     r = DeleteFile(msifile);
4425     ok(r == TRUE, "file didn't exist after commit\n");
4426 }
4427
4428 static void test_update(void)
4429 {
4430     MSIHANDLE hdb = 0, view = 0, rec = 0;
4431     CHAR result[MAX_PATH];
4432     const char *query;
4433     DWORD size;
4434     UINT r;
4435
4436     /* just MsiOpenDatabase should not create a file */
4437     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4438     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4439
4440     /* create the Control table */
4441     query = "CREATE TABLE `Control` ( "
4442         "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4443         "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4444         "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4445         "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4446     r = MsiDatabaseOpenView(hdb, query, &view);
4447     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4448     r = MsiViewExecute(view, 0);
4449     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4450     r = MsiViewClose(view);
4451     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4452     r = MsiCloseHandle(view);
4453     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4454
4455     /* add a control */
4456     query = "INSERT INTO `Control` ( "
4457         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4458         "`Property`, `Text`, `Control_Next`, `Help` )"
4459         "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4460     r = MsiDatabaseOpenView(hdb, query, &view);
4461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4462     r = MsiViewExecute(view, 0);
4463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4464     r = MsiViewClose(view);
4465     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4466     r = MsiCloseHandle(view);
4467     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4468
4469     /* add a second control */
4470     query = "INSERT INTO `Control` ( "
4471         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4472         "`Property`, `Text`, `Control_Next`, `Help` )"
4473         "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
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     r = MsiViewClose(view);
4479     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4480     r = MsiCloseHandle(view);
4481     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4482
4483     /* add a third control */
4484     query = "INSERT INTO `Control` ( "
4485         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4486         "`Property`, `Text`, `Control_Next`, `Help` )"
4487         "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4488     r = MsiDatabaseOpenView(hdb, query, &view);
4489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4490     r = MsiViewExecute(view, 0);
4491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4492     r = MsiViewClose(view);
4493     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4494     r = MsiCloseHandle(view);
4495     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4496
4497     /* bad table */
4498     query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4499     r = MsiDatabaseOpenView(hdb, query, &view);
4500     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4501
4502     /* bad set column */
4503     query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4504     r = MsiDatabaseOpenView(hdb, query, &view);
4505     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4506
4507     /* bad where condition */
4508     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4509     r = MsiDatabaseOpenView(hdb, query, &view);
4510     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4511
4512     /* just the dialog_ specified */
4513     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4514     r = MsiDatabaseOpenView(hdb, query, &view);
4515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4516     r = MsiViewExecute(view, 0);
4517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4518     r = MsiViewClose(view);
4519     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4520     r = MsiCloseHandle(view);
4521     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4522
4523     /* check the modified text */
4524     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4525     r = MsiDatabaseOpenView(hdb, query, &view);
4526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4527     r = MsiViewExecute(view, 0);
4528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4529
4530     r = MsiViewFetch(view, &rec);
4531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4532
4533     size = MAX_PATH;
4534     r = MsiRecordGetString(rec, 1, result, &size);
4535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4536     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4537
4538     MsiCloseHandle(rec);
4539
4540     r = MsiViewFetch(view, &rec);
4541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4542
4543     size = MAX_PATH;
4544     r = MsiRecordGetString(rec, 1, result, &size);
4545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4546     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4547
4548     MsiCloseHandle(rec);
4549
4550     r = MsiViewFetch(view, &rec);
4551     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4552
4553     r = MsiViewClose(view);
4554     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4555     r = MsiCloseHandle(view);
4556     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4557
4558     /* dialog_ and control specified */
4559     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4560     r = MsiDatabaseOpenView(hdb, query, &view);
4561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4562     r = MsiViewExecute(view, 0);
4563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4564     r = MsiViewClose(view);
4565     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4566     r = MsiCloseHandle(view);
4567     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4568
4569     /* check the modified text */
4570     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4571     r = MsiDatabaseOpenView(hdb, query, &view);
4572     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4573     r = MsiViewExecute(view, 0);
4574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4575
4576     r = MsiViewFetch(view, &rec);
4577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4578
4579     size = MAX_PATH;
4580     r = MsiRecordGetString(rec, 1, result, &size);
4581     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4582     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4583
4584     MsiCloseHandle(rec);
4585
4586     r = MsiViewFetch(view, &rec);
4587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4588
4589     size = MAX_PATH;
4590     r = MsiRecordGetString(rec, 1, result, &size);
4591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4592     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4593
4594     MsiCloseHandle(rec);
4595
4596     r = MsiViewFetch(view, &rec);
4597     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4598
4599     r = MsiViewClose(view);
4600     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4601     r = MsiCloseHandle(view);
4602     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4603
4604     /* no where condition */
4605     query = "UPDATE `Control` SET `Text` = 'this is text'";
4606     r = MsiDatabaseOpenView(hdb, query, &view);
4607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4608     r = MsiViewExecute(view, 0);
4609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4610     r = MsiViewClose(view);
4611     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4612     r = MsiCloseHandle(view);
4613     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4614
4615     /* check the modified text */
4616     query = "SELECT `Text` FROM `Control`";
4617     r = MsiDatabaseOpenView(hdb, query, &view);
4618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4619     r = MsiViewExecute(view, 0);
4620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4621
4622     r = MsiViewFetch(view, &rec);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624
4625     size = MAX_PATH;
4626     r = MsiRecordGetString(rec, 1, result, &size);
4627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4628     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4629
4630     MsiCloseHandle(rec);
4631
4632     r = MsiViewFetch(view, &rec);
4633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4634
4635     size = MAX_PATH;
4636     r = MsiRecordGetString(rec, 1, result, &size);
4637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4638     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4639
4640     MsiCloseHandle(rec);
4641
4642     r = MsiViewFetch(view, &rec);
4643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4644
4645     size = MAX_PATH;
4646     r = MsiRecordGetString(rec, 1, result, &size);
4647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4648     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4649
4650     MsiCloseHandle(rec);
4651
4652     r = MsiViewFetch(view, &rec);
4653     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4654
4655     r = MsiViewClose(view);
4656     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4657     r = MsiCloseHandle(view);
4658     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4659
4660     query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4661         "`Orange` CHAR(72),  `Pear` INT PRIMARY KEY `Banana`)";
4662     r = run_query(hdb, 0, query);
4663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4664
4665     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4666         "VALUES('one', 'two', 3)";
4667     r = run_query(hdb, 0, query);
4668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4669
4670     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4671         "VALUES('three', 'four', 5)";
4672     r = run_query(hdb, 0, query);
4673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4674
4675     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4676         "VALUES('six', 'two', 7)";
4677     r = run_query(hdb, 0, query);
4678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4679
4680     rec = MsiCreateRecord(2);
4681     MsiRecordSetInteger(rec, 1, 8);
4682     MsiRecordSetString(rec, 2, "two");
4683
4684     query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4685     r = run_query(hdb, rec, query);
4686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4687
4688     MsiCloseHandle(rec);
4689
4690     query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4691     r = MsiDatabaseOpenView(hdb, query, &view);
4692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4693     r = MsiViewExecute(view, 0);
4694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4695
4696     r = MsiViewFetch(view, &rec);
4697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4698
4699     r = MsiRecordGetInteger(rec, 1);
4700     ok(r == 8, "Expected 8, got %d\n", r);
4701
4702     MsiCloseHandle(rec);
4703
4704     r = MsiViewFetch(view, &rec);
4705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4706
4707     r = MsiRecordGetInteger(rec, 1);
4708     ok(r == 8, "Expected 8, got %d\n", r);
4709
4710     MsiCloseHandle(rec);
4711
4712     r = MsiViewFetch(view, &rec);
4713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4714
4715     r = MsiRecordGetInteger(rec, 1);
4716     ok(r == 5, "Expected 5, got %d\n", r);
4717
4718     MsiCloseHandle(rec);
4719
4720     r = MsiViewFetch(view, &rec);
4721     ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4722
4723     MsiViewClose(view);
4724     MsiCloseHandle(view);
4725
4726     r = MsiDatabaseCommit(hdb);
4727     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4728     r = MsiCloseHandle(hdb);
4729     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4730
4731     DeleteFile(msifile);
4732 }
4733
4734 static void test_special_tables(void)
4735 {
4736     const char *query;
4737     MSIHANDLE hdb = 0;
4738     UINT r;
4739
4740     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4741     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4742
4743     query = "CREATE TABLE `_Properties` ( "
4744         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4745     r = run_query(hdb, 0, query);
4746     ok(r == ERROR_SUCCESS, "failed to create table\n");
4747
4748     query = "CREATE TABLE `_Storages` ( "
4749         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4750     r = run_query(hdb, 0, query);
4751     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4752
4753     query = "CREATE TABLE `_Streams` ( "
4754         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4755     r = run_query(hdb, 0, query);
4756     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4757
4758     query = "CREATE TABLE `_Tables` ( "
4759         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4760     r = run_query(hdb, 0, query);
4761     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4762
4763     query = "CREATE TABLE `_Columns` ( "
4764         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4765     r = run_query(hdb, 0, query);
4766     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4767
4768     r = MsiCloseHandle(hdb);
4769     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4770 }
4771
4772 static void test_tables_order(void)
4773 {
4774     const char *query;
4775     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4776     UINT r;
4777     char buffer[100];
4778     DWORD sz;
4779
4780     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4781     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4782
4783     query = "CREATE TABLE `foo` ( "
4784         "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4785     r = run_query(hdb, 0, query);
4786     ok(r == ERROR_SUCCESS, "failed to create table\n");
4787
4788     query = "CREATE TABLE `bar` ( "
4789         "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4790     r = run_query(hdb, 0, query);
4791     ok(r == ERROR_SUCCESS, "failed to create table\n");
4792
4793     query = "CREATE TABLE `baz` ( "
4794         "`bar` INT NOT NULL, "
4795         "`baz` INT NOT NULL, "
4796         "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4797     r = run_query(hdb, 0, query);
4798     ok(r == ERROR_SUCCESS, "failed to create table\n");
4799
4800     /* The names of the tables in the _Tables table must
4801        be in the same order as these names are created in
4802        the strings table. */
4803     query = "SELECT * FROM `_Tables`";
4804     r = MsiDatabaseOpenView(hdb, query, &hview);
4805     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4806     r = MsiViewExecute(hview, 0);
4807     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4808
4809     r = MsiViewFetch(hview, &hrec);
4810     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4811     sz = sizeof(buffer);
4812     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4814     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4815     r = MsiCloseHandle(hrec);
4816     ok(r == ERROR_SUCCESS, "failed to close record\n");
4817
4818     r = MsiViewFetch(hview, &hrec);
4819     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4820     sz = sizeof(buffer);
4821     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4823     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4824     r = MsiCloseHandle(hrec);
4825     ok(r == ERROR_SUCCESS, "failed to close record\n");
4826
4827     r = MsiViewFetch(hview, &hrec);
4828     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4829     sz = sizeof(buffer);
4830     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4832     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4833     r = MsiCloseHandle(hrec);
4834     ok(r == ERROR_SUCCESS, "failed to close record\n");
4835
4836     r = MsiViewClose(hview);
4837     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4838     r = MsiCloseHandle(hview);
4839     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4840
4841     /* The names of the tables in the _Columns table must
4842        be in the same order as these names are created in
4843        the strings table. */
4844     query = "SELECT * FROM `_Columns`";
4845     r = MsiDatabaseOpenView(hdb, query, &hview);
4846     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4847     r = MsiViewExecute(hview, 0);
4848     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4849
4850     r = MsiViewFetch(hview, &hrec);
4851     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4852     sz = sizeof(buffer);
4853     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4855     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4856     sz = sizeof(buffer);
4857     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4858     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4859     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4860     r = MsiCloseHandle(hrec);
4861     ok(r == ERROR_SUCCESS, "failed to close record\n");
4862
4863     r = MsiViewFetch(hview, &hrec);
4864     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4865     sz = sizeof(buffer);
4866     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4868     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4869     sz = sizeof(buffer);
4870     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4872     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4873     r = MsiCloseHandle(hrec);
4874     ok(r == ERROR_SUCCESS, "failed to close record\n");
4875
4876     r = MsiViewFetch(hview, &hrec);
4877     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4878     sz = sizeof(buffer);
4879     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4881     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4882     sz = sizeof(buffer);
4883     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4885     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4886     r = MsiCloseHandle(hrec);
4887     ok(r == ERROR_SUCCESS, "failed to close record\n");
4888
4889     r = MsiViewFetch(hview, &hrec);
4890     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4891     sz = sizeof(buffer);
4892     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4894     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4895     sz = sizeof(buffer);
4896     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4898     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4899     r = MsiCloseHandle(hrec);
4900     ok(r == ERROR_SUCCESS, "failed to close record\n");
4901
4902     r = MsiViewFetch(hview, &hrec);
4903     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4904     sz = sizeof(buffer);
4905     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4907     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4908     sz = sizeof(buffer);
4909     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4910     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4911     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4912     r = MsiCloseHandle(hrec);
4913     ok(r == ERROR_SUCCESS, "failed to close record\n");
4914
4915     r = MsiViewClose(hview);
4916     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4917     r = MsiCloseHandle(hview);
4918     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4919
4920     r = MsiCloseHandle(hdb);
4921     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4922
4923     DeleteFile(msifile);
4924 }
4925
4926 static void test_rows_order(void)
4927 {
4928     const char *query;
4929     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4930     UINT r;
4931     char buffer[100];
4932     DWORD sz;
4933
4934     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4935     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4936
4937     query = "CREATE TABLE `foo` ( "
4938         "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4939     r = run_query(hdb, 0, query);
4940     ok(r == ERROR_SUCCESS, "failed to create table\n");
4941
4942     r = run_query(hdb, 0, "INSERT INTO `foo` "
4943             "( `bar` ) VALUES ( 'A' )");
4944     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4945
4946     r = run_query(hdb, 0, "INSERT INTO `foo` "
4947             "( `bar` ) VALUES ( 'B' )");
4948     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4949
4950     r = run_query(hdb, 0, "INSERT INTO `foo` "
4951             "( `bar` ) VALUES ( 'C' )");
4952     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4953
4954     r = run_query(hdb, 0, "INSERT INTO `foo` "
4955             "( `bar` ) VALUES ( 'D' )");
4956     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4957
4958     r = run_query(hdb, 0, "INSERT INTO `foo` "
4959             "( `bar` ) VALUES ( 'E' )");
4960     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4961
4962     r = run_query(hdb, 0, "INSERT INTO `foo` "
4963             "( `bar` ) VALUES ( 'F' )");
4964     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4965
4966     query = "CREATE TABLE `bar` ( "
4967         "`foo` LONGCHAR NOT NULL, "
4968         "`baz` LONGCHAR NOT NULL "
4969         "PRIMARY KEY `foo` )";
4970     r = run_query(hdb, 0, query);
4971     ok(r == ERROR_SUCCESS, "failed to create table\n");
4972
4973     r = run_query(hdb, 0, "INSERT INTO `bar` "
4974             "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4975     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4976
4977     r = run_query(hdb, 0, "INSERT INTO `bar` "
4978             "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4979     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4980
4981     r = run_query(hdb, 0, "INSERT INTO `bar` "
4982             "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4983     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4984
4985     r = run_query(hdb, 0, "INSERT INTO `bar` "
4986             "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4987     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4988
4989     /* The rows of the table must be ordered by the column values of
4990        each row. For strings, the column value is the string id
4991        in the string table.  */
4992
4993     query = "SELECT * FROM `bar`";
4994     r = MsiDatabaseOpenView(hdb, query, &hview);
4995     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4996     r = MsiViewExecute(hview, 0);
4997     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4998
4999     r = MsiViewFetch(hview, &hrec);
5000     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5001     sz = sizeof(buffer);
5002     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5004     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
5005     sz = sizeof(buffer);
5006     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5008     ok(!lstrcmp(buffer, "B"), "Expected B, got %s\n", buffer);
5009     r = MsiCloseHandle(hrec);
5010     ok(r == ERROR_SUCCESS, "failed to close record\n");
5011
5012     r = MsiViewFetch(hview, &hrec);
5013     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5014     sz = sizeof(buffer);
5015     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5017     ok(!lstrcmp(buffer, "C"), "Expected E, got %s\n", buffer);
5018     sz = sizeof(buffer);
5019     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5021     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
5022     r = MsiCloseHandle(hrec);
5023     ok(r == ERROR_SUCCESS, "failed to close record\n");
5024
5025     r = MsiViewFetch(hview, &hrec);
5026     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5027     sz = sizeof(buffer);
5028     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5030     ok(!lstrcmp(buffer, "D"), "Expected D, got %s\n", buffer);
5031     sz = sizeof(buffer);
5032     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5034     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
5035     r = MsiCloseHandle(hrec);
5036     ok(r == ERROR_SUCCESS, "failed to close record\n");
5037
5038     r = MsiViewFetch(hview, &hrec);
5039     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5040     sz = sizeof(buffer);
5041     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5043     ok(!lstrcmp(buffer, "F"), "Expected F, got %s\n", buffer);
5044     sz = sizeof(buffer);
5045     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5046     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5047     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
5048     r = MsiCloseHandle(hrec);
5049     ok(r == ERROR_SUCCESS, "failed to close record\n");
5050
5051     r = MsiViewClose(hview);
5052     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5053     r = MsiCloseHandle(hview);
5054     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5055
5056     r = MsiCloseHandle(hdb);
5057     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5058
5059     DeleteFile(msifile);
5060 }
5061
5062 static void test_collation(void)
5063 {
5064     static const WCHAR query1[] =
5065         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5066          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5067          '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
5068     static const WCHAR query2[] =
5069         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5070          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5071          '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
5072     static const WCHAR query3[] =
5073         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
5074          '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
5075            ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
5076            'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
5077     static const WCHAR query4[] =
5078         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
5079          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5080          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5081     static const WCHAR query5[] =
5082         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
5083          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5084          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5085     static const WCHAR query6[] =
5086         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
5087          ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
5088     static const WCHAR letter_C[] = {'C',0};
5089     static const WCHAR letter_D[] = {'D',0};
5090     static const WCHAR letter_a_ring[] = {'a',0x30a,0};
5091     static const WCHAR letter_a_with_ring[] = {0xe5,0};
5092     const char *query;
5093     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5094     UINT r;
5095     char buffer[100];
5096     WCHAR bufferW[100];
5097     DWORD sz;
5098
5099     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5100     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5101
5102     query = "CREATE TABLE `bar` ( "
5103         "`foo` LONGCHAR NOT NULL, "
5104         "`baz` LONGCHAR NOT NULL "
5105         "PRIMARY KEY `foo` )";
5106     r = run_query(hdb, 0, query);
5107     ok(r == ERROR_SUCCESS, "failed to create table\n");
5108
5109     r = run_query(hdb, 0, query);
5110     ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
5111
5112     r = run_query(hdb, 0, "INSERT INTO `bar` "
5113             "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
5114     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5115
5116     r = run_query(hdb, 0, "INSERT INTO `bar` "
5117             "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
5118     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5119
5120     r = run_queryW(hdb, 0, query1);
5121     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5122
5123     r = run_queryW(hdb, 0, query2);
5124     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5125
5126     r = run_queryW(hdb, 0, query3);
5127     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5128
5129     r = run_queryW(hdb, 0, query4);
5130     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5131
5132     r = run_queryW(hdb, 0, query5);
5133     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5134
5135     query = "SELECT * FROM `bar`";
5136     r = MsiDatabaseOpenView(hdb, query, &hview);
5137     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5138     r = MsiViewExecute(hview, 0);
5139     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5140
5141     r = MsiViewFetch(hview, &hrec);
5142     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5143     sz = sizeof(buffer);
5144     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5146     ok(!lstrcmp(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
5147     sz = sizeof(buffer);
5148     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5150     ok(!lstrcmp(buffer, "A"), "Expected A, got '%s'\n", buffer);
5151     MsiCloseHandle(hrec);
5152
5153     r = MsiViewFetch(hview, &hrec);
5154     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5155     sz = sizeof(buffer);
5156     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5157     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5158     ok(!lstrcmp(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
5159     sz = sizeof(buffer);
5160     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5162     ok(!lstrcmp(buffer, "B"), "Expected B, got '%s'\n", buffer);
5163     MsiCloseHandle(hrec);
5164
5165     r = MsiViewFetch(hview, &hrec);
5166     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5167     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5168     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5170     ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)),
5171        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
5172     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5173     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5175     ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
5176     MsiCloseHandle(hrec);
5177
5178     r = MsiViewFetch(hview, &hrec);
5179     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5180     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5181     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5183     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5184        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5185     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5186     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5188     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5189     MsiCloseHandle(hrec);
5190
5191     r = MsiViewClose(hview);
5192     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5193     r = MsiCloseHandle(hview);
5194     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5195
5196     r = MsiDatabaseOpenViewW(hdb, query6, &hview);
5197     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5198     r = MsiViewExecute(hview, 0);
5199     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5200
5201     r = MsiViewFetch(hview, &hrec);
5202     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5203     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5204     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5206     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5207        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5208     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5209     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5211     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5212     MsiCloseHandle(hrec);
5213
5214     r = MsiViewFetch(hview, &hrec);
5215     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
5216
5217     r = MsiViewClose(hview);
5218     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5219     r = MsiCloseHandle(hview);
5220     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5221
5222     r = MsiCloseHandle(hdb);
5223     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5224
5225     DeleteFile(msifile);
5226 }
5227
5228 static void test_select_markers(void)
5229 {
5230     MSIHANDLE hdb = 0, rec, view, res;
5231     LPCSTR query;
5232     UINT r;
5233     DWORD size;
5234     CHAR buf[MAX_PATH];
5235
5236     hdb = create_db();
5237     ok( hdb, "failed to create db\n");
5238
5239     r = run_query(hdb, 0,
5240             "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
5241     ok(r == S_OK, "cannot create table: %d\n", r);
5242
5243     r = run_query(hdb, 0, "INSERT INTO `Table` "
5244             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
5245     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5246
5247     r = run_query(hdb, 0, "INSERT INTO `Table` "
5248             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
5249     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5250
5251     r = run_query(hdb, 0, "INSERT INTO `Table` "
5252             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
5253     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5254
5255     r = run_query(hdb, 0, "INSERT INTO `Table` "
5256             "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
5257     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5258
5259     rec = MsiCreateRecord(2);
5260     MsiRecordSetString(rec, 1, "apple");
5261     MsiRecordSetString(rec, 2, "two");
5262
5263     query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
5264     r = MsiDatabaseOpenView(hdb, query, &view);
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5266
5267     r = MsiViewExecute(view, rec);
5268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5269
5270     r = MsiViewFetch(view, &res);
5271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5272
5273     size = MAX_PATH;
5274     r = MsiRecordGetString(res, 1, buf, &size);
5275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5276     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5277
5278     size = MAX_PATH;
5279     r = MsiRecordGetString(res, 2, buf, &size);
5280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5281     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5282
5283     r = MsiRecordGetInteger(res, 3);
5284     ok(r == 1, "Expected 1, got %d\n", r);
5285
5286     MsiCloseHandle(res);
5287
5288     r = MsiViewFetch(view, &res);
5289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5290
5291     size = MAX_PATH;
5292     r = MsiRecordGetString(res, 1, buf, &size);
5293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5294     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5295
5296     size = MAX_PATH;
5297     r = MsiRecordGetString(res, 2, buf, &size);
5298     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5299     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5300
5301     r = MsiRecordGetInteger(res, 3);
5302     ok(r == 2, "Expected 2, got %d\n", r);
5303
5304     MsiCloseHandle(res);
5305
5306     r = MsiViewFetch(view, &res);
5307     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5308
5309     MsiCloseHandle(rec);
5310     MsiViewClose(view);
5311     MsiCloseHandle(view);
5312
5313     rec = MsiCreateRecord(2);
5314     MsiRecordSetString(rec, 1, "one");
5315     MsiRecordSetInteger(rec, 2, 1);
5316
5317     query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5318     r = MsiDatabaseOpenView(hdb, query, &view);
5319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5320     r = MsiViewExecute(view, rec);
5321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5322
5323     r = MsiViewFetch(view, &res);
5324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5325
5326     size = MAX_PATH;
5327     r = MsiRecordGetString(res, 1, buf, &size);
5328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5329     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5330
5331     size = MAX_PATH;
5332     r = MsiRecordGetString(res, 2, buf, &size);
5333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5334     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5335
5336     r = MsiRecordGetInteger(res, 3);
5337     ok(r == 2, "Expected 2, got %d\n", r);
5338
5339     MsiCloseHandle(res);
5340
5341     r = MsiViewFetch(view, &res);
5342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5343
5344     size = MAX_PATH;
5345     r = MsiRecordGetString(res, 1, buf, &size);
5346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5347     ok(!lstrcmp(buf, "banana"), "Expected banana, got %s\n", buf);
5348
5349     size = MAX_PATH;
5350     r = MsiRecordGetString(res, 2, buf, &size);
5351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5352     ok(!lstrcmp(buf, "three"), "Expected three, got %s\n", buf);
5353
5354     r = MsiRecordGetInteger(res, 3);
5355     ok(r == 3, "Expected 3, got %d\n", r);
5356
5357     MsiCloseHandle(res);
5358
5359     r = MsiViewFetch(view, &res);
5360     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5361
5362     MsiCloseHandle(rec);
5363     MsiViewClose(view);
5364     MsiCloseHandle(view);
5365     MsiCloseHandle(hdb);
5366     DeleteFile(msifile);
5367 }
5368
5369 static void test_viewmodify_update(void)
5370 {
5371     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5372     UINT i, test_max, offset, count;
5373     const char *query;
5374     UINT r;
5375
5376     DeleteFile(msifile);
5377
5378     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5379     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5380
5381     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5382     r = run_query( hdb, 0, query );
5383     ok(r == ERROR_SUCCESS, "query failed\n");
5384
5385     query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5386     r = run_query( hdb, 0, query );
5387     ok(r == ERROR_SUCCESS, "query failed\n");
5388
5389     query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5390     r = run_query( hdb, 0, query );
5391     ok(r == ERROR_SUCCESS, "query failed\n");
5392
5393     query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5394     r = run_query( hdb, 0, query );
5395     ok(r == ERROR_SUCCESS, "query failed\n");
5396
5397     query = "SELECT `B` FROM `table`";
5398     r = MsiDatabaseOpenView(hdb, query, &hview);
5399     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5400     r = MsiViewExecute(hview, 0);
5401     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5402     r = MsiViewFetch(hview, &hrec);
5403     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5404
5405     r = MsiRecordSetInteger(hrec, 1, 0);
5406     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5407
5408     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5409     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5410
5411     r = MsiCloseHandle(hrec);
5412     ok(r == ERROR_SUCCESS, "failed to close record\n");
5413
5414     r = MsiViewClose(hview);
5415     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5416     r = MsiCloseHandle(hview);
5417     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5418
5419     query = "SELECT * FROM `table`";
5420     r = MsiDatabaseOpenView(hdb, query, &hview);
5421     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5422     r = MsiViewExecute(hview, 0);
5423     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5424     r = MsiViewFetch(hview, &hrec);
5425     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5426
5427     r = MsiRecordGetInteger(hrec, 1);
5428     ok(r == 1, "Expected 1, got %d\n", r);
5429     r = MsiRecordGetInteger(hrec, 2);
5430     ok(r == 0, "Expected 0, got %d\n", r);
5431
5432     r = MsiCloseHandle(hrec);
5433     ok(r == ERROR_SUCCESS, "failed to close record\n");
5434
5435     r = MsiViewFetch(hview, &hrec);
5436     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5437
5438     r = MsiRecordGetInteger(hrec, 1);
5439     ok(r == 3, "Expected 3, got %d\n", r);
5440     r = MsiRecordGetInteger(hrec, 2);
5441     ok(r == 4, "Expected 4, got %d\n", r);
5442
5443     r = MsiCloseHandle(hrec);
5444     ok(r == ERROR_SUCCESS, "failed to close record\n");
5445
5446     r = MsiViewFetch(hview, &hrec);
5447     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5448
5449     r = MsiRecordGetInteger(hrec, 1);
5450     ok(r == 5, "Expected 5, got %d\n", r);
5451     r = MsiRecordGetInteger(hrec, 2);
5452     ok(r == 6, "Expected 6, got %d\n", r);
5453
5454     r = MsiCloseHandle(hrec);
5455     ok(r == ERROR_SUCCESS, "failed to close record\n");
5456
5457     r = MsiViewFetch(hview, &hrec);
5458     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5459
5460     r = MsiViewClose(hview);
5461     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5462     r = MsiCloseHandle(hview);
5463     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5464
5465     /* loop through all elements */
5466     query = "SELECT `B` FROM `table`";
5467     r = MsiDatabaseOpenView(hdb, query, &hview);
5468     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5469     r = MsiViewExecute(hview, 0);
5470     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5471
5472     while (TRUE)
5473     {
5474         r = MsiViewFetch(hview, &hrec);
5475         if (r != ERROR_SUCCESS)
5476             break;
5477
5478         r = MsiRecordSetInteger(hrec, 1, 0);
5479         ok(r == ERROR_SUCCESS, "failed to set integer\n");
5480
5481         r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5482         ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5483
5484         r = MsiCloseHandle(hrec);
5485         ok(r == ERROR_SUCCESS, "failed to close record\n");
5486     }
5487
5488     r = MsiViewClose(hview);
5489     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5490     r = MsiCloseHandle(hview);
5491     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5492
5493     query = "SELECT * FROM `table`";
5494     r = MsiDatabaseOpenView(hdb, query, &hview);
5495     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5496     r = MsiViewExecute(hview, 0);
5497     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5498     r = MsiViewFetch(hview, &hrec);
5499     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5500
5501     r = MsiRecordGetInteger(hrec, 1);
5502     ok(r == 1, "Expected 1, got %d\n", r);
5503     r = MsiRecordGetInteger(hrec, 2);
5504     ok(r == 0, "Expected 0, got %d\n", r);
5505
5506     r = MsiCloseHandle(hrec);
5507     ok(r == ERROR_SUCCESS, "failed to close record\n");
5508
5509     r = MsiViewFetch(hview, &hrec);
5510     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5511
5512     r = MsiRecordGetInteger(hrec, 1);
5513     ok(r == 3, "Expected 3, got %d\n", r);
5514     r = MsiRecordGetInteger(hrec, 2);
5515     ok(r == 0, "Expected 0, got %d\n", r);
5516
5517     r = MsiCloseHandle(hrec);
5518     ok(r == ERROR_SUCCESS, "failed to close record\n");
5519
5520     r = MsiViewFetch(hview, &hrec);
5521     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5522
5523     r = MsiRecordGetInteger(hrec, 1);
5524     ok(r == 5, "Expected 5, got %d\n", r);
5525     r = MsiRecordGetInteger(hrec, 2);
5526     ok(r == 0, "Expected 0, got %d\n", r);
5527
5528     r = MsiCloseHandle(hrec);
5529     ok(r == ERROR_SUCCESS, "failed to close record\n");
5530
5531     r = MsiViewFetch(hview, &hrec);
5532     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5533
5534     r = MsiViewClose(hview);
5535     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5536     r = MsiCloseHandle(hview);
5537     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5538
5539     query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5540     r = run_query( hdb, 0, query );
5541     ok(r == ERROR_SUCCESS, "query failed\n");
5542
5543     query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5544     r = MsiDatabaseOpenView( hdb, query, &hview );
5545     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5546
5547     test_max = 100;
5548     offset = 1234;
5549     for(i = 0; i < test_max; i++)
5550     {
5551
5552         hrec = MsiCreateRecord( 2 );
5553         MsiRecordSetInteger( hrec, 1, test_max - i );
5554         MsiRecordSetInteger( hrec, 2, i );
5555
5556         r = MsiViewExecute( hview, hrec );
5557         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5558
5559         r = MsiCloseHandle( hrec );
5560         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5561     }
5562
5563     r = MsiViewClose( hview );
5564     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5565     r = MsiCloseHandle( hview );
5566     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5567
5568     /* Update. */
5569     query = "SELECT * FROM `table2` ORDER BY `B`";
5570     r = MsiDatabaseOpenView( hdb, query, &hview);
5571     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5572     r = MsiViewExecute( hview, 0 );
5573     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5574
5575     count = 0;
5576     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5577     {
5578         UINT b = MsiRecordGetInteger( hrec, 2 );
5579
5580         r = MsiRecordSetInteger( hrec, 2, b + offset);
5581         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5582
5583         r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5584         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5585
5586         r = MsiCloseHandle(hrec);
5587         ok(r == ERROR_SUCCESS, "failed to close record\n");
5588         count++;
5589     }
5590     ok(count == test_max, "Got count %d\n", count);
5591
5592     r = MsiViewClose(hview);
5593     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5594     r = MsiCloseHandle(hview);
5595     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5596
5597     /* Recheck. */
5598     query = "SELECT * FROM `table2` ORDER BY `B`";
5599     r = MsiDatabaseOpenView( hdb, query, &hview);
5600     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5601     r = MsiViewExecute( hview, 0 );
5602     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5603
5604     count = 0;
5605     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5606     {
5607         UINT a = MsiRecordGetInteger( hrec, 1 );
5608         UINT b = MsiRecordGetInteger( hrec, 2 );
5609         ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5610             a, b, test_max - a + offset, b);
5611
5612         r = MsiCloseHandle(hrec);
5613         ok(r == ERROR_SUCCESS, "failed to close record\n");
5614         count++;
5615     }
5616     ok(count == test_max, "Got count %d\n", count);
5617
5618     r = MsiViewClose(hview);
5619     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5620     r = MsiCloseHandle(hview);
5621     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5622
5623     r = MsiCloseHandle( hdb );
5624     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5625 }
5626
5627 static void test_viewmodify_assign(void)
5628 {
5629     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5630     const char *query;
5631     UINT r;
5632
5633     /* setup database */
5634     DeleteFile(msifile);
5635
5636     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5637     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5638
5639     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5640     r = run_query( hdb, 0, query );
5641     ok(r == ERROR_SUCCESS, "query failed\n");
5642
5643     /* assign to view, new primary key */
5644     query = "SELECT * FROM `table`";
5645     r = MsiDatabaseOpenView(hdb, query, &hview);
5646     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5647     r = MsiViewExecute(hview, 0);
5648     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5649
5650     hrec = MsiCreateRecord(2);
5651     ok(hrec != 0, "MsiCreateRecord failed\n");
5652
5653     r = MsiRecordSetInteger(hrec, 1, 1);
5654     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5655     r = MsiRecordSetInteger(hrec, 2, 2);
5656     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5657
5658     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5659     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5660
5661     r = MsiCloseHandle(hrec);
5662     ok(r == ERROR_SUCCESS, "failed to close record\n");
5663
5664     r = MsiViewClose(hview);
5665     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5666     r = MsiCloseHandle(hview);
5667     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5668
5669     query = "SELECT * FROM `table`";
5670     r = MsiDatabaseOpenView(hdb, query, &hview);
5671     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5672     r = MsiViewExecute(hview, 0);
5673     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5674     r = MsiViewFetch(hview, &hrec);
5675     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5676
5677     r = MsiRecordGetInteger(hrec, 1);
5678     ok(r == 1, "Expected 1, got %d\n", r);
5679     r = MsiRecordGetInteger(hrec, 2);
5680     ok(r == 2, "Expected 2, got %d\n", r);
5681
5682     r = MsiCloseHandle(hrec);
5683     ok(r == ERROR_SUCCESS, "failed to close record\n");
5684
5685     r = MsiViewFetch(hview, &hrec);
5686     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5687
5688     r = MsiViewClose(hview);
5689     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5690     r = MsiCloseHandle(hview);
5691     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5692
5693     /* assign to view, primary key matches */
5694     query = "SELECT * FROM `table`";
5695     r = MsiDatabaseOpenView(hdb, query, &hview);
5696     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5697     r = MsiViewExecute(hview, 0);
5698     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5699
5700     hrec = MsiCreateRecord(2);
5701     ok(hrec != 0, "MsiCreateRecord failed\n");
5702
5703     r = MsiRecordSetInteger(hrec, 1, 1);
5704     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5705     r = MsiRecordSetInteger(hrec, 2, 4);
5706     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5707
5708     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5709     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5710
5711     r = MsiCloseHandle(hrec);
5712     ok(r == ERROR_SUCCESS, "failed to close record\n");
5713
5714     r = MsiViewClose(hview);
5715     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5716     r = MsiCloseHandle(hview);
5717     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5718
5719     query = "SELECT * FROM `table`";
5720     r = MsiDatabaseOpenView(hdb, query, &hview);
5721     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5722     r = MsiViewExecute(hview, 0);
5723     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5724     r = MsiViewFetch(hview, &hrec);
5725     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5726
5727     r = MsiRecordGetInteger(hrec, 1);
5728     ok(r == 1, "Expected 1, got %d\n", r);
5729     r = MsiRecordGetInteger(hrec, 2);
5730     ok(r == 4, "Expected 4, got %d\n", r);
5731
5732     r = MsiCloseHandle(hrec);
5733     ok(r == ERROR_SUCCESS, "failed to close record\n");
5734
5735     r = MsiViewFetch(hview, &hrec);
5736     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5737
5738     r = MsiViewClose(hview);
5739     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5740     r = MsiCloseHandle(hview);
5741     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5742
5743     /* close database */
5744     r = MsiCloseHandle( hdb );
5745     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5746 }
5747
5748 static const WCHAR data10[] = { /* MOO */
5749     0x8001, 0x000b,
5750 };
5751 static const WCHAR data11[] = { /* AAR */
5752     0x8002, 0x8005,
5753     0x000c, 0x000f,
5754 };
5755 static const char data12[] = /* _StringData */
5756     "MOOABAARCDonetwofourfive";
5757 static const WCHAR data13[] = { /* _StringPool */
5758 /*  len, refs */
5759     0,   0,    /* string 0 ''     */
5760     0,   0,    /* string 1 ''     */
5761     0,   0,    /* string 2 ''     */
5762     0,   0,    /* string 3 ''     */
5763     0,   0,    /* string 4 ''     */
5764     3,   3,    /* string 5 'MOO'  */
5765     1,   1,    /* string 6 'A'    */
5766     1,   1,    /* string 7 'B'    */
5767     3,   3,    /* string 8 'AAR'  */
5768     1,   1,    /* string 9 'C'    */
5769     1,   1,    /* string a 'D'    */
5770     3,   1,    /* string b 'one'  */
5771     3,   1,    /* string c 'two'  */
5772     0,   0,    /* string d ''     */
5773     4,   1,    /* string e 'four' */
5774     4,   1,    /* string f 'five' */
5775 };
5776
5777 static void test_stringtable(void)
5778 {
5779     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5780     IStorage *stg = NULL;
5781     IStream *stm;
5782     WCHAR name[0x20];
5783     HRESULT hr;
5784     const char *query;
5785     char buffer[MAX_PATH];
5786     WCHAR data[MAX_PATH];
5787     DWORD sz, read;
5788     UINT r;
5789
5790     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5791     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5792     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5793     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5794     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5795
5796     DeleteFile(msifile);
5797
5798     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5799     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5800
5801     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5802     r = run_query(hdb, 0, query);
5803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5804
5805     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5806     r = run_query(hdb, 0, query);
5807     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5808
5809     /* insert persistent row */
5810     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5811     r = run_query(hdb, 0, query);
5812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5813
5814     /* insert persistent row */
5815     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5816     r = run_query(hdb, 0, query);
5817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5818
5819     /* open a view */
5820     query = "SELECT * FROM `MOO`";
5821     r = MsiDatabaseOpenView(hdb, query, &hview);
5822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5823     r = MsiViewExecute(hview, 0);
5824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5825
5826     hrec = MsiCreateRecord(2);
5827
5828     r = MsiRecordSetInteger(hrec, 1, 3);
5829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5830     r = MsiRecordSetString(hrec, 2, "three");
5831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5832
5833     /* insert a nonpersistent row */
5834     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5836
5837     r = MsiCloseHandle(hrec);
5838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5839     r = MsiViewClose(hview);
5840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5841     r = MsiCloseHandle(hview);
5842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5843
5844     /* insert persistent row */
5845     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5846     r = run_query(hdb, 0, query);
5847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5848
5849     /* insert persistent row */
5850     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5851     r = run_query(hdb, 0, query);
5852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5853
5854     r = MsiDatabaseCommit(hdb);
5855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5856
5857     r = MsiCloseHandle(hdb);
5858     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5859
5860     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
5861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5862
5863     query = "SELECT * FROM `MOO`";
5864     r = MsiDatabaseOpenView(hdb, query, &hview);
5865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5866
5867     r = MsiViewExecute(hview, 0);
5868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5869
5870     r = MsiViewFetch(hview, &hrec);
5871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5872
5873     r = MsiRecordGetFieldCount(hrec);
5874     ok(r == 2, "Expected 2, got %d\n", r);
5875
5876     r = MsiRecordGetInteger(hrec, 1);
5877     ok(r == 1, "Expected 1, got %d\n", r);
5878
5879     sz = sizeof(buffer);
5880     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5882     ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
5883
5884     r = MsiCloseHandle(hrec);
5885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5886
5887     r = MsiViewFetch(hview, &hrec);
5888     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5889
5890     r = MsiViewClose(hview);
5891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5892     r = MsiCloseHandle(hview);
5893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5894     r = MsiCloseHandle(hrec);
5895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5896
5897     query = "SELECT * FROM `AAR`";
5898     r = MsiDatabaseOpenView(hdb, query, &hview);
5899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5900
5901     r = MsiViewExecute(hview, 0);
5902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5903
5904     r = MsiViewFetch(hview, &hrec);
5905     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5906
5907     r = MsiRecordGetFieldCount(hrec);
5908     ok(r == 2, "Expected 2, got %d\n", r);
5909
5910     r = MsiRecordGetInteger(hrec, 1);
5911     ok(r == 2, "Expected 2, got %d\n", r);
5912
5913     sz = sizeof(buffer);
5914     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5916     ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
5917
5918     r = MsiCloseHandle(hrec);
5919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5920
5921     r = MsiViewFetch(hview, &hrec);
5922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5923
5924     r = MsiRecordGetFieldCount(hrec);
5925     ok(r == 2, "Expected 2, got %d\n", r);
5926
5927     r = MsiRecordGetInteger(hrec, 1);
5928     ok(r == 5, "Expected 5, got %d\n", r);
5929
5930     sz = sizeof(buffer);
5931     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5933     ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
5934
5935     r = MsiCloseHandle(hrec);
5936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5937
5938     r = MsiViewFetch(hview, &hrec);
5939     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5940
5941     r = MsiViewClose(hview);
5942     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5943     r = MsiCloseHandle(hview);
5944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5945     r = MsiCloseHandle(hrec);
5946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5947     r = MsiCloseHandle(hdb);
5948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5949
5950     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5951     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5952     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5953     ok(stg != NULL, "Expected non-NULL storage\n");
5954
5955     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5956     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5957     ok(stm != NULL, "Expected non-NULL stream\n");
5958
5959     hr = IStream_Read(stm, data, MAX_PATH, &read);
5960     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5961     ok(read == 4, "Expected 4, got %d\n", read);
5962     todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5963
5964     hr = IStream_Release(stm);
5965     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5966
5967     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5968     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5969     ok(stm != NULL, "Expected non-NULL stream\n");
5970
5971     hr = IStream_Read(stm, data, MAX_PATH, &read);
5972     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5973     ok(read == 8, "Expected 8, got %d\n", read);
5974     todo_wine
5975     {
5976         ok(!memcmp(data, data11, read), "Unexpected data\n");
5977     }
5978
5979     hr = IStream_Release(stm);
5980     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5981
5982     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5983     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5984     ok(stm != NULL, "Expected non-NULL stream\n");
5985
5986     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5987     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5988     ok(read == 24, "Expected 24, got %d\n", read);
5989     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5990
5991     hr = IStream_Release(stm);
5992     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5993
5994     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5995     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5996     ok(stm != NULL, "Expected non-NULL stream\n");
5997
5998     hr = IStream_Read(stm, data, MAX_PATH, &read);
5999     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6000     todo_wine
6001     {
6002         ok(read == 64, "Expected 64, got %d\n", read);
6003         ok(!memcmp(data, data13, read), "Unexpected data\n");
6004     }
6005
6006     hr = IStream_Release(stm);
6007     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6008
6009     hr = IStorage_Release(stg);
6010     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6011
6012     DeleteFileA(msifile);
6013 }
6014
6015 static void test_viewmodify_delete(void)
6016 {
6017     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
6018     UINT r;
6019     const char *query;
6020     char buffer[0x100];
6021     DWORD sz;
6022
6023     DeleteFile(msifile);
6024
6025     /* just MsiOpenDatabase should not create a file */
6026     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6028
6029     query = "CREATE TABLE `phone` ( "
6030             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
6031             "PRIMARY KEY `id`)";
6032     r = run_query(hdb, 0, query);
6033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6034
6035     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6036         "VALUES('1', 'Alan', '5030581')";
6037     r = run_query(hdb, 0, query);
6038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6039
6040     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6041         "VALUES('2', 'Barry', '928440')";
6042     r = run_query(hdb, 0, query);
6043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6044
6045     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6046         "VALUES('3', 'Cindy', '2937550')";
6047     r = run_query(hdb, 0, query);
6048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6049
6050     query = "SELECT * FROM `phone` WHERE `id` <= 2";
6051     r = MsiDatabaseOpenView(hdb, query, &hview);
6052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6053     r = MsiViewExecute(hview, 0);
6054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6055     r = MsiViewFetch(hview, &hrec);
6056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6057
6058     /* delete 1 */
6059     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6061
6062     r = MsiCloseHandle(hrec);
6063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6064     r = MsiViewFetch(hview, &hrec);
6065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6066
6067     /* delete 2 */
6068     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6070
6071     r = MsiCloseHandle(hrec);
6072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6073     r = MsiViewClose(hview);
6074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6075     r = MsiCloseHandle(hview);
6076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6077
6078     query = "SELECT * FROM `phone`";
6079     r = MsiDatabaseOpenView(hdb, query, &hview);
6080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6081     r = MsiViewExecute(hview, 0);
6082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6083     r = MsiViewFetch(hview, &hrec);
6084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6085
6086     r = MsiRecordGetInteger(hrec, 1);
6087     ok(r == 3, "Expected 3, got %d\n", r);
6088
6089     sz = sizeof(buffer);
6090     r = MsiRecordGetString(hrec, 2, buffer, &sz);
6091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6092     ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
6093
6094     sz = sizeof(buffer);
6095     r = MsiRecordGetString(hrec, 3, buffer, &sz);
6096     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6097     ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
6098
6099     r = MsiCloseHandle(hrec);
6100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6101
6102     r = MsiViewFetch(hview, &hrec);
6103     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6104
6105     r = MsiViewClose(hview);
6106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6107     r = MsiCloseHandle(hview);
6108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6109     r = MsiCloseHandle(hdb);
6110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6111 }
6112
6113 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
6114 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
6115 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
6116
6117 static const WCHAR data14[] = { /* _StringPool */
6118 /*  len, refs */
6119     0,   0,    /* string 0 ''    */
6120 };
6121
6122 static const struct {
6123     LPCWSTR name;
6124     const void *data;
6125     DWORD size;
6126 } database_table_data[] =
6127 {
6128     {_Tables, NULL, 0},
6129     {_StringData, NULL, 0},
6130     {_StringPool, data14, sizeof data14},
6131 };
6132
6133 static void enum_stream_names(IStorage *stg)
6134 {
6135     IEnumSTATSTG *stgenum = NULL;
6136     IStream *stm;
6137     HRESULT hr;
6138     STATSTG stat;
6139     ULONG n, count;
6140     BYTE data[MAX_PATH];
6141     BYTE check[MAX_PATH];
6142     DWORD sz;
6143
6144     memset(check, 'a', MAX_PATH);
6145
6146     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
6147     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6148
6149     n = 0;
6150     while(TRUE)
6151     {
6152         count = 0;
6153         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
6154         if(FAILED(hr) || !count)
6155             break;
6156
6157         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
6158            "Expected table %d name to match\n", n);
6159
6160         stm = NULL;
6161         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
6162                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6163         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6164         ok(stm != NULL, "Expected non-NULL stream\n");
6165
6166         CoTaskMemFree(stat.pwcsName);
6167
6168         sz = MAX_PATH;
6169         memset(data, 'a', MAX_PATH);
6170         hr = IStream_Read(stm, data, sz, &count);
6171         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6172
6173         ok(count == database_table_data[n].size,
6174            "Expected %d, got %d\n", database_table_data[n].size, count);
6175
6176         if (!database_table_data[n].size)
6177             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
6178         else
6179             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
6180                "Expected table %d data to match\n", n);
6181
6182         IStream_Release(stm);
6183         n++;
6184     }
6185
6186     ok(n == 3, "Expected 3, got %d\n", n);
6187
6188     IEnumSTATSTG_Release(stgenum);
6189 }
6190
6191 static void test_defaultdatabase(void)
6192 {
6193     UINT r;
6194     HRESULT hr;
6195     MSIHANDLE hdb;
6196     IStorage *stg = NULL;
6197
6198     DeleteFile(msifile);
6199
6200     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6202
6203     r = MsiDatabaseCommit(hdb);
6204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6205
6206     MsiCloseHandle(hdb);
6207
6208     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6209     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6210     ok(stg != NULL, "Expected non-NULL stg\n");
6211
6212     enum_stream_names(stg);
6213
6214     IStorage_Release(stg);
6215     DeleteFileA(msifile);
6216 }
6217
6218 static void test_order(void)
6219 {
6220     MSIHANDLE hdb, hview, hrec;
6221     CHAR buffer[MAX_PATH];
6222     LPCSTR query;
6223     UINT r, sz;
6224     int val;
6225
6226     hdb = create_db();
6227     ok(hdb, "failed to create db\n");
6228
6229     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6230     r = run_query(hdb, 0, query);
6231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6232
6233     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6234     r = run_query(hdb, 0, query);
6235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6236
6237     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6238     r = run_query(hdb, 0, query);
6239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6240
6241     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6242     r = run_query(hdb, 0, query);
6243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6244
6245     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6246     r = run_query(hdb, 0, query);
6247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6248
6249     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6250     r = run_query(hdb, 0, query);
6251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6252
6253     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6254     r = run_query(hdb, 0, query);
6255     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6256
6257     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6258     r = run_query(hdb, 0, query);
6259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6260
6261     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6262     r = run_query(hdb, 0, query);
6263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6264
6265     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6266     r = MsiDatabaseOpenView(hdb, query, &hview);
6267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6268     r = MsiViewExecute(hview, 0);
6269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6270
6271     r = MsiViewFetch(hview, &hrec);
6272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6273
6274     val = MsiRecordGetInteger(hrec, 1);
6275     ok(val == 3, "Expected 3, got %d\n", val);
6276
6277     val = MsiRecordGetInteger(hrec, 2);
6278     ok(val == 4, "Expected 3, got %d\n", val);
6279
6280     MsiCloseHandle(hrec);
6281
6282     r = MsiViewFetch(hview, &hrec);
6283     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6284
6285     val = MsiRecordGetInteger(hrec, 1);
6286     ok(val == 5, "Expected 5, got %d\n", val);
6287
6288     val = MsiRecordGetInteger(hrec, 2);
6289     ok(val == 6, "Expected 6, got %d\n", val);
6290
6291     MsiCloseHandle(hrec);
6292
6293     r = MsiViewFetch(hview, &hrec);
6294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6295
6296     val = MsiRecordGetInteger(hrec, 1);
6297     ok(val == 1, "Expected 1, got %d\n", val);
6298
6299     val = MsiRecordGetInteger(hrec, 2);
6300     ok(val == 2, "Expected 2, got %d\n", val);
6301
6302     MsiCloseHandle(hrec);
6303
6304     r = MsiViewFetch(hview, &hrec);
6305     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6306
6307     MsiViewClose(hview);
6308     MsiCloseHandle(hview);
6309
6310     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6311     r = MsiDatabaseOpenView(hdb, query, &hview);
6312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6313     r = MsiViewExecute(hview, 0);
6314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6315
6316     r = MsiViewFetch(hview, &hrec);
6317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6318
6319     val = MsiRecordGetInteger(hrec, 1);
6320     ok(val == 1, "Expected 1, got %d\n", val);
6321
6322     val = MsiRecordGetInteger(hrec, 2);
6323     ok(val == 12, "Expected 12, got %d\n", val);
6324
6325     MsiCloseHandle(hrec);
6326
6327     r = MsiViewFetch(hview, &hrec);
6328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6329
6330     val = MsiRecordGetInteger(hrec, 1);
6331     ok(val == 3, "Expected 3, got %d\n", val);
6332
6333     val = MsiRecordGetInteger(hrec, 2);
6334     ok(val == 12, "Expected 12, got %d\n", val);
6335
6336     MsiCloseHandle(hrec);
6337
6338     r = MsiViewFetch(hview, &hrec);
6339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6340
6341     val = MsiRecordGetInteger(hrec, 1);
6342     ok(val == 5, "Expected 5, got %d\n", val);
6343
6344     val = MsiRecordGetInteger(hrec, 2);
6345     ok(val == 12, "Expected 12, got %d\n", val);
6346
6347     MsiCloseHandle(hrec);
6348
6349     r = MsiViewFetch(hview, &hrec);
6350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6351
6352     val = MsiRecordGetInteger(hrec, 1);
6353     ok(val == 1, "Expected 1, got %d\n", val);
6354
6355     val = MsiRecordGetInteger(hrec, 2);
6356     ok(val == 14, "Expected 14, got %d\n", val);
6357
6358     MsiCloseHandle(hrec);
6359
6360     r = MsiViewFetch(hview, &hrec);
6361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6362
6363     val = MsiRecordGetInteger(hrec, 1);
6364     ok(val == 3, "Expected 3, got %d\n", val);
6365
6366     val = MsiRecordGetInteger(hrec, 2);
6367     ok(val == 14, "Expected 14, got %d\n", val);
6368
6369     MsiCloseHandle(hrec);
6370
6371     r = MsiViewFetch(hview, &hrec);
6372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6373
6374     val = MsiRecordGetInteger(hrec, 1);
6375     ok(val == 5, "Expected 5, got %d\n", val);
6376
6377     val = MsiRecordGetInteger(hrec, 2);
6378     ok(val == 14, "Expected 14, got %d\n", val);
6379
6380     MsiCloseHandle(hrec);
6381
6382     r = MsiViewFetch(hview, &hrec);
6383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6384
6385     val = MsiRecordGetInteger(hrec, 1);
6386     ok(val == 1, "Expected 1, got %d\n", val);
6387
6388     val = MsiRecordGetInteger(hrec, 2);
6389     ok(val == 10, "Expected 10, got %d\n", val);
6390
6391     MsiCloseHandle(hrec);
6392
6393     r = MsiViewFetch(hview, &hrec);
6394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6395
6396     val = MsiRecordGetInteger(hrec, 1);
6397     ok(val == 3, "Expected 3, got %d\n", val);
6398
6399     val = MsiRecordGetInteger(hrec, 2);
6400     ok(val == 10, "Expected 10, got %d\n", val);
6401
6402     MsiCloseHandle(hrec);
6403
6404     r = MsiViewFetch(hview, &hrec);
6405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6406
6407     val = MsiRecordGetInteger(hrec, 1);
6408     ok(val == 5, "Expected 5, got %d\n", val);
6409
6410     val = MsiRecordGetInteger(hrec, 2);
6411     ok(val == 10, "Expected 10, got %d\n", val);
6412
6413     MsiCloseHandle(hrec);
6414
6415     r = MsiViewFetch(hview, &hrec);
6416     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6417
6418     MsiViewClose(hview);
6419     MsiCloseHandle(hview);
6420
6421     query = "SELECT * FROM `Empty` ORDER BY `A`";
6422     r = MsiDatabaseOpenView(hdb, query, &hview);
6423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6424     r = MsiViewExecute(hview, 0);
6425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6426
6427     r = MsiViewFetch(hview, &hrec);
6428     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6429
6430     MsiViewClose(hview);
6431     MsiCloseHandle(hview);
6432
6433     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6434     r = run_query(hdb, 0, query);
6435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6436
6437     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6438     r = run_query(hdb, 0, query);
6439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6440
6441     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6442     r = run_query(hdb, 0, query);
6443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6444
6445     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6446     r = run_query(hdb, 0, query);
6447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6448
6449     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6450     r = MsiDatabaseOpenView(hdb, query, &hview);
6451     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6452     r = MsiViewExecute(hview, 0);
6453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6454
6455     r = MsiViewFetch(hview, &hrec);
6456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6457
6458     sz = sizeof(buffer);
6459     r = MsiRecordGetString(hrec, 1, buffer, &sz);
6460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6461     ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6462
6463     r = MsiRecordGetInteger(hrec, 2);
6464     ok(r == 3, "Expected 3, got %d\n", r);
6465
6466     MsiCloseHandle(hrec);
6467
6468     r = MsiViewFetch(hview, &hrec);
6469     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6470
6471     MsiViewClose(hview);
6472     MsiCloseHandle(hview);
6473     MsiCloseHandle(hdb);
6474 }
6475
6476 static void test_viewmodify_delete_temporary(void)
6477 {
6478     MSIHANDLE hdb, hview, hrec;
6479     const char *query;
6480     UINT r;
6481
6482     DeleteFile(msifile);
6483
6484     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6485     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6486
6487     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6488     r = run_query(hdb, 0, query);
6489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6490
6491     query = "SELECT * FROM `Table`";
6492     r = MsiDatabaseOpenView(hdb, query, &hview);
6493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6494     r = MsiViewExecute(hview, 0);
6495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6496
6497     hrec = MsiCreateRecord(1);
6498     MsiRecordSetInteger(hrec, 1, 1);
6499
6500     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6502
6503     MsiCloseHandle(hrec);
6504
6505     hrec = MsiCreateRecord(1);
6506     MsiRecordSetInteger(hrec, 1, 2);
6507
6508     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6510
6511     MsiCloseHandle(hrec);
6512
6513     hrec = MsiCreateRecord(1);
6514     MsiRecordSetInteger(hrec, 1, 3);
6515
6516     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6518
6519     MsiCloseHandle(hrec);
6520
6521     hrec = MsiCreateRecord(1);
6522     MsiRecordSetInteger(hrec, 1, 4);
6523
6524     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6526
6527     MsiCloseHandle(hrec);
6528     MsiViewClose(hview);
6529     MsiCloseHandle(hview);
6530
6531     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6532     r = MsiDatabaseOpenView(hdb, query, &hview);
6533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6534     r = MsiViewExecute(hview, 0);
6535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6536     r = MsiViewFetch(hview, &hrec);
6537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6538
6539     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6541
6542     MsiCloseHandle(hrec);
6543     MsiViewClose(hview);
6544     MsiCloseHandle(hview);
6545
6546     query = "SELECT * FROM `Table` WHERE  `A` = 3";
6547     r = MsiDatabaseOpenView(hdb, query, &hview);
6548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6549     r = MsiViewExecute(hview, 0);
6550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6551     r = MsiViewFetch(hview, &hrec);
6552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6553
6554     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6555     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6556
6557     MsiCloseHandle(hrec);
6558     MsiViewClose(hview);
6559     MsiCloseHandle(hview);
6560
6561     query = "SELECT * FROM `Table` ORDER BY `A`";
6562     r = MsiDatabaseOpenView(hdb, query, &hview);
6563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6564     r = MsiViewExecute(hview, 0);
6565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6566
6567     r = MsiViewFetch(hview, &hrec);
6568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6569
6570     r = MsiRecordGetInteger(hrec, 1);
6571     ok(r == 1, "Expected 1, got %d\n", r);
6572
6573     MsiCloseHandle(hrec);
6574
6575     r = MsiViewFetch(hview, &hrec);
6576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6577
6578     r = MsiRecordGetInteger(hrec, 1);
6579     ok(r == 4, "Expected 4, got %d\n", r);
6580
6581     MsiCloseHandle(hrec);
6582
6583     r = MsiViewFetch(hview, &hrec);
6584     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6585
6586     MsiViewClose(hview);
6587     MsiCloseHandle(hview);
6588     MsiCloseHandle(hdb);
6589     DeleteFileA(msifile);
6590 }
6591
6592 static void test_deleterow(void)
6593 {
6594     MSIHANDLE hdb, hview, hrec;
6595     const char *query;
6596     char buf[MAX_PATH];
6597     UINT r;
6598     DWORD size;
6599
6600     DeleteFile(msifile);
6601
6602     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6604
6605     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6606     r = run_query(hdb, 0, query);
6607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6608
6609     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6610     r = run_query(hdb, 0, query);
6611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6612
6613     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6614     r = run_query(hdb, 0, query);
6615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6616
6617     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6618     r = run_query(hdb, 0, query);
6619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6620
6621     r = MsiDatabaseCommit(hdb);
6622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6623
6624     MsiCloseHandle(hdb);
6625
6626     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
6627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6628
6629     query = "SELECT * FROM `Table`";
6630     r = MsiDatabaseOpenView(hdb, query, &hview);
6631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6632     r = MsiViewExecute(hview, 0);
6633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6634
6635     r = MsiViewFetch(hview, &hrec);
6636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6637
6638     size = MAX_PATH;
6639     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6641     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6642
6643     MsiCloseHandle(hrec);
6644
6645     r = MsiViewFetch(hview, &hrec);
6646     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6647
6648     MsiViewClose(hview);
6649     MsiCloseHandle(hview);
6650     MsiCloseHandle(hdb);
6651     DeleteFileA(msifile);
6652 }
6653
6654 static const CHAR import_dat[] = "A\n"
6655                                  "s72\n"
6656                                  "Table\tA\n"
6657                                  "This is a new 'string' ok\n";
6658
6659 static void test_quotes(void)
6660 {
6661     MSIHANDLE hdb, hview, hrec;
6662     const char *query;
6663     char buf[MAX_PATH];
6664     UINT r;
6665     DWORD size;
6666
6667     DeleteFile(msifile);
6668
6669     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6671
6672     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6673     r = run_query(hdb, 0, query);
6674     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6675
6676     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6677     r = run_query(hdb, 0, query);
6678     ok(r == ERROR_BAD_QUERY_SYNTAX,
6679        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6680
6681     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6682     r = run_query(hdb, 0, query);
6683     ok(r == ERROR_BAD_QUERY_SYNTAX,
6684        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6685
6686     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6687     r = run_query(hdb, 0, query);
6688     ok(r == ERROR_BAD_QUERY_SYNTAX,
6689        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6690
6691     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6692     r = run_query(hdb, 0, query);
6693     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6694
6695     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6696     r = run_query(hdb, 0, query);
6697     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6698
6699     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6700     r = run_query(hdb, 0, query);
6701     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6702
6703     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6704     r = run_query(hdb, 0, query);
6705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6706
6707     query = "SELECT * FROM `Table`";
6708     r = MsiDatabaseOpenView(hdb, query, &hview);
6709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6710
6711     r = MsiViewExecute(hview, 0);
6712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6713
6714     r = MsiViewFetch(hview, &hrec);
6715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6716
6717     size = MAX_PATH;
6718     r = MsiRecordGetString(hrec, 1, buf, &size);
6719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6720     ok(!lstrcmp(buf, "This is a \"string\" ok"),
6721        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6722
6723     MsiCloseHandle(hrec);
6724
6725     r = MsiViewFetch(hview, &hrec);
6726     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6727
6728     MsiViewClose(hview);
6729     MsiCloseHandle(hview);
6730
6731     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6732
6733     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6735
6736     DeleteFileA("import.idt");
6737
6738     query = "SELECT * FROM `Table`";
6739     r = MsiDatabaseOpenView(hdb, query, &hview);
6740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6741
6742     r = MsiViewExecute(hview, 0);
6743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6744
6745     r = MsiViewFetch(hview, &hrec);
6746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6747
6748     size = MAX_PATH;
6749     r = MsiRecordGetString(hrec, 1, buf, &size);
6750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6751     ok(!lstrcmp(buf, "This is a new 'string' ok"),
6752        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6753
6754     MsiCloseHandle(hrec);
6755
6756     r = MsiViewFetch(hview, &hrec);
6757     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6758
6759     MsiViewClose(hview);
6760     MsiCloseHandle(hview);
6761     MsiCloseHandle(hdb);
6762     DeleteFileA(msifile);
6763 }
6764
6765 static void test_carriagereturn(void)
6766 {
6767     MSIHANDLE hdb, hview, hrec;
6768     const char *query;
6769     char buf[MAX_PATH];
6770     UINT r;
6771     DWORD size;
6772
6773     DeleteFile(msifile);
6774
6775     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6777
6778     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6779     r = run_query(hdb, 0, query);
6780     ok(r == ERROR_BAD_QUERY_SYNTAX,
6781        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6782
6783     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6784     r = run_query(hdb, 0, query);
6785     ok(r == ERROR_BAD_QUERY_SYNTAX,
6786        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6787
6788     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6789     r = run_query(hdb, 0, query);
6790     ok(r == ERROR_BAD_QUERY_SYNTAX,
6791        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6792
6793     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6794     r = run_query(hdb, 0, query);
6795     ok(r == ERROR_BAD_QUERY_SYNTAX,
6796        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6797
6798     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6799     r = run_query(hdb, 0, query);
6800     ok(r == ERROR_BAD_QUERY_SYNTAX,
6801        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6802
6803     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6804     r = run_query(hdb, 0, query);
6805     ok(r == ERROR_BAD_QUERY_SYNTAX,
6806        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6807
6808     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6809     r = run_query(hdb, 0, query);
6810     ok(r == ERROR_BAD_QUERY_SYNTAX,
6811        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6812
6813     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6814     r = run_query(hdb, 0, query);
6815     ok(r == ERROR_BAD_QUERY_SYNTAX,
6816        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6817
6818     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6819     r = run_query(hdb, 0, query);
6820     ok(r == ERROR_BAD_QUERY_SYNTAX,
6821        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6822
6823     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6824     r = run_query(hdb, 0, query);
6825     ok(r == ERROR_BAD_QUERY_SYNTAX,
6826        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6827
6828     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6829     r = run_query(hdb, 0, query);
6830     ok(r == ERROR_BAD_QUERY_SYNTAX,
6831        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6832
6833     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6834     r = run_query(hdb, 0, query);
6835     ok(r == ERROR_BAD_QUERY_SYNTAX,
6836        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6837
6838     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6839     r = run_query(hdb, 0, query);
6840     ok(r == ERROR_BAD_QUERY_SYNTAX,
6841        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6842
6843     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6844     r = run_query(hdb, 0, query);
6845     ok(r == ERROR_BAD_QUERY_SYNTAX,
6846        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6847
6848     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6849     r = run_query(hdb, 0, query);
6850     ok(r == ERROR_BAD_QUERY_SYNTAX,
6851        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6852
6853     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6854     r = run_query(hdb, 0, query);
6855     ok(r == ERROR_BAD_QUERY_SYNTAX,
6856        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6857
6858     query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6859     r = run_query(hdb, 0, query);
6860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6861
6862     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6863     r = run_query(hdb, 0, query);
6864     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6865
6866     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6867     r = run_query(hdb, 0, query);
6868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6869
6870     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6871     r = run_query(hdb, 0, query);
6872     ok(r == ERROR_BAD_QUERY_SYNTAX,
6873        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6874
6875     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6876     r = run_query(hdb, 0, query);
6877     ok(r == ERROR_BAD_QUERY_SYNTAX,
6878        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6879
6880     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6881     r = run_query(hdb, 0, query);
6882     ok(r == ERROR_BAD_QUERY_SYNTAX,
6883        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6884
6885     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6886     r = run_query(hdb, 0, query);
6887     ok(r == ERROR_BAD_QUERY_SYNTAX,
6888        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6889
6890     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6891     r = run_query(hdb, 0, query);
6892     ok(r == ERROR_BAD_QUERY_SYNTAX,
6893        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6894
6895     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6896     r = run_query(hdb, 0, query);
6897     ok(r == ERROR_BAD_QUERY_SYNTAX,
6898        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6899
6900     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6901     r = run_query(hdb, 0, query);
6902     ok(r == ERROR_BAD_QUERY_SYNTAX,
6903        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6904
6905     query = "SELECT * FROM `_Tables`";
6906     r = MsiDatabaseOpenView(hdb, query, &hview);
6907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6908     r = MsiViewExecute(hview, 0);
6909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6910
6911     r = MsiViewFetch(hview, &hrec);
6912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6913
6914     size = MAX_PATH;
6915     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6917     ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6918
6919     MsiCloseHandle(hrec);
6920
6921     r = MsiViewFetch(hview, &hrec);
6922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6923
6924     size = MAX_PATH;
6925     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6927     ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6928
6929     MsiCloseHandle(hrec);
6930
6931     r = MsiViewFetch(hview, &hrec);
6932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6933
6934     size = MAX_PATH;
6935     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6937     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6938
6939     MsiCloseHandle(hrec);
6940
6941     r = MsiViewFetch(hview, &hrec);
6942     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6943
6944     MsiViewClose(hview);
6945     MsiCloseHandle(hview);
6946
6947     MsiCloseHandle(hdb);
6948     DeleteFileA(msifile);
6949 }
6950
6951 static void test_noquotes(void)
6952 {
6953     MSIHANDLE hdb, hview, hrec;
6954     const char *query;
6955     char buf[MAX_PATH];
6956     UINT r;
6957     DWORD size;
6958
6959     DeleteFile(msifile);
6960
6961     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6963
6964     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6965     r = run_query(hdb, 0, query);
6966     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6967
6968     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6969     r = run_query(hdb, 0, query);
6970     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6971
6972     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6973     r = run_query(hdb, 0, query);
6974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6975
6976     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6977     r = run_query(hdb, 0, query);
6978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6979
6980     query = "SELECT * FROM `_Tables`";
6981     r = MsiDatabaseOpenView(hdb, query, &hview);
6982     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6983     r = MsiViewExecute(hview, 0);
6984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6985
6986     r = MsiViewFetch(hview, &hrec);
6987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6988
6989     size = MAX_PATH;
6990     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6992     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6993
6994     MsiCloseHandle(hrec);
6995
6996     r = MsiViewFetch(hview, &hrec);
6997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6998
6999     size = MAX_PATH;
7000     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7002     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
7003
7004     MsiCloseHandle(hrec);
7005
7006     r = MsiViewFetch(hview, &hrec);
7007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7008
7009     size = MAX_PATH;
7010     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7012     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7013
7014     MsiCloseHandle(hrec);
7015
7016     r = MsiViewFetch(hview, &hrec);
7017     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7018
7019     MsiViewClose(hview);
7020     MsiCloseHandle(hview);
7021
7022     query = "SELECT * FROM `_Columns`";
7023     r = MsiDatabaseOpenView(hdb, query, &hview);
7024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7025     r = MsiViewExecute(hview, 0);
7026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7027
7028     r = MsiViewFetch(hview, &hrec);
7029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7030
7031     size = MAX_PATH;
7032     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7034     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
7035
7036     r = MsiRecordGetInteger(hrec, 2);
7037     ok(r == 1, "Expected 1, got %d\n", r);
7038
7039     size = MAX_PATH;
7040     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7042     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7043
7044     MsiCloseHandle(hrec);
7045
7046     r = MsiViewFetch(hview, &hrec);
7047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7048
7049     size = MAX_PATH;
7050     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7052     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
7053
7054     r = MsiRecordGetInteger(hrec, 2);
7055     ok(r == 1, "Expected 1, got %d\n", r);
7056
7057     size = MAX_PATH;
7058     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7060     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7061
7062     MsiCloseHandle(hrec);
7063
7064     r = MsiViewFetch(hview, &hrec);
7065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7066
7067     size = MAX_PATH;
7068     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7070     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7071
7072     r = MsiRecordGetInteger(hrec, 2);
7073     ok(r == 1, "Expected 1, got %d\n", r);
7074
7075     size = MAX_PATH;
7076     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7078     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7079
7080     MsiCloseHandle(hrec);
7081
7082     r = MsiViewFetch(hview, &hrec);
7083     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7084
7085     MsiViewClose(hview);
7086     MsiCloseHandle(hview);
7087
7088     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
7089     r = run_query(hdb, 0, query);
7090     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7091
7092     query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
7093     r = run_query(hdb, 0, query);
7094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7095
7096     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
7097     r = run_query(hdb, 0, query);
7098     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7099
7100     query = "SELECT * FROM Table WHERE `A` = 'hi'";
7101     r = run_query(hdb, 0, query);
7102     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7103
7104     query = "SELECT * FROM `Table` WHERE `A` = hi";
7105     r = run_query(hdb, 0, query);
7106     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7107
7108     query = "SELECT * FROM Table";
7109     r = run_query(hdb, 0, query);
7110     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7111
7112     query = "SELECT * FROM Table2";
7113     r = MsiDatabaseOpenView(hdb, query, &hview);
7114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7115     r = MsiViewExecute(hview, 0);
7116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7117
7118     r = MsiViewFetch(hview, &hrec);
7119     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7120
7121     MsiViewClose(hview);
7122     MsiCloseHandle(hview);
7123
7124     query = "SELECT * FROM `Table` WHERE A = 'hi'";
7125     r = MsiDatabaseOpenView(hdb, query, &hview);
7126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7127     r = MsiViewExecute(hview, 0);
7128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7129
7130     r = MsiViewFetch(hview, &hrec);
7131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7132
7133     size = MAX_PATH;
7134     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7136     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7137
7138     MsiCloseHandle(hrec);
7139
7140     r = MsiViewFetch(hview, &hrec);
7141     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7142
7143     MsiViewClose(hview);
7144     MsiCloseHandle(hview);
7145     MsiCloseHandle(hdb);
7146     DeleteFileA(msifile);
7147 }
7148
7149 static void read_file_data(LPCSTR filename, LPSTR buffer)
7150 {
7151     HANDLE file;
7152     DWORD read;
7153
7154     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
7155     ZeroMemory(buffer, MAX_PATH);
7156     ReadFile(file, buffer, MAX_PATH, &read, NULL);
7157     CloseHandle(file);
7158 }
7159
7160 static void test_forcecodepage(void)
7161 {
7162     MSIHANDLE hdb;
7163     const char *query;
7164     char buffer[MAX_PATH];
7165     UINT r;
7166
7167     DeleteFile(msifile);
7168     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
7169
7170     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172
7173     query = "SELECT * FROM `_ForceCodepage`";
7174     r = run_query(hdb, 0, query);
7175     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7176
7177     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7178     r = run_query(hdb, 0, query);
7179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7180
7181     query = "SELECT * FROM `_ForceCodepage`";
7182     r = run_query(hdb, 0, query);
7183     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7184
7185     r = MsiDatabaseCommit(hdb);
7186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7187
7188     query = "SELECT * FROM `_ForceCodepage`";
7189     r = run_query(hdb, 0, query);
7190     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7191
7192     MsiCloseHandle(hdb);
7193
7194     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb);
7195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7196
7197     query = "SELECT * FROM `_ForceCodepage`";
7198     r = run_query(hdb, 0, query);
7199     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7200
7201     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7203
7204     read_file_data("forcecodepage.idt", buffer);
7205     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7206        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7207
7208     create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7209
7210     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7212
7213     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7215
7216     read_file_data("forcecodepage.idt", buffer);
7217     ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
7218        "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7219
7220     create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
7221
7222     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7223     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_SUCCESS, got %d\n", r);
7224
7225     MsiCloseHandle(hdb);
7226     DeleteFileA(msifile);
7227     DeleteFileA("forcecodepage.idt");
7228 }
7229
7230 static void test_viewmodify_refresh(void)
7231 {
7232     MSIHANDLE hdb, hview, hrec;
7233     const char *query;
7234     char buffer[MAX_PATH];
7235     UINT r;
7236     DWORD size;
7237
7238     DeleteFile(msifile);
7239
7240     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7242
7243     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7244     r = run_query(hdb, 0, query);
7245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7246
7247     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7248     r = run_query(hdb, 0, query);
7249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7250
7251     query = "SELECT * FROM `Table`";
7252     r = MsiDatabaseOpenView(hdb, query, &hview);
7253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7254     r = MsiViewExecute(hview, 0);
7255     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7256
7257     r = MsiViewFetch(hview, &hrec);
7258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7259
7260     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7261     r = run_query(hdb, 0, query);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263
7264     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7266
7267     size = MAX_PATH;
7268     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7270     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7271     ok(size == 2, "Expected 2, got %d\n", size);
7272
7273     r = MsiRecordGetInteger(hrec, 2);
7274     ok(r == 2, "Expected 2, got %d\n", r);
7275
7276     MsiCloseHandle(hrec);
7277     MsiViewClose(hview);
7278     MsiCloseHandle(hview);
7279
7280     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7281     r = run_query(hdb, 0, query);
7282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7283
7284     query = "SELECT * FROM `Table` WHERE `B` = 3";
7285     r = MsiDatabaseOpenView(hdb, query, &hview);
7286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287     r = MsiViewExecute(hview, 0);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289
7290     r = MsiViewFetch(hview, &hrec);
7291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7292
7293     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7294     r = run_query(hdb, 0, query);
7295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7296
7297     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7298     r = run_query(hdb, 0, query);
7299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7300
7301     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7303
7304     size = MAX_PATH;
7305     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7307     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7308     ok(size == 5, "Expected 5, got %d\n", size);
7309
7310     r = MsiRecordGetInteger(hrec, 2);
7311     ok(r == 2, "Expected 2, got %d\n", r);
7312
7313     MsiCloseHandle(hrec);
7314     MsiViewClose(hview);
7315     MsiCloseHandle(hview);
7316     MsiCloseHandle(hdb);
7317     DeleteFileA(msifile);
7318 }
7319
7320 static void test_where_viewmodify(void)
7321 {
7322     MSIHANDLE hdb, hview, hrec;
7323     const char *query;
7324     UINT r;
7325
7326     DeleteFile(msifile);
7327
7328     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7330
7331     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7332     r = run_query(hdb, 0, query);
7333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7334
7335     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7336     r = run_query(hdb, 0, query);
7337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7338
7339     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7340     r = run_query(hdb, 0, query);
7341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7342
7343     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7344     r = run_query(hdb, 0, query);
7345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7346
7347     /* `B` = 3 doesn't match, but the view shouldn't be executed */
7348     query = "SELECT * FROM `Table` WHERE `B` = 3";
7349     r = MsiDatabaseOpenView(hdb, query, &hview);
7350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7351
7352     hrec = MsiCreateRecord(2);
7353     MsiRecordSetInteger(hrec, 1, 7);
7354     MsiRecordSetInteger(hrec, 2, 8);
7355
7356     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7358
7359     MsiCloseHandle(hrec);
7360     MsiViewClose(hview);
7361     MsiCloseHandle(hview);
7362
7363     query = "SELECT * FROM `Table` WHERE `A` = 7";
7364     r = MsiDatabaseOpenView(hdb, query, &hview);
7365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7366     r = MsiViewExecute(hview, 0);
7367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7368
7369     r = MsiViewFetch(hview, &hrec);
7370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7371
7372     r = MsiRecordGetInteger(hrec, 1);
7373     ok(r == 7, "Expected 7, got %d\n", r);
7374
7375     r = MsiRecordGetInteger(hrec, 2);
7376     ok(r == 8, "Expected 8, got %d\n", r);
7377
7378     MsiRecordSetInteger(hrec, 2, 9);
7379
7380     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7382
7383     MsiCloseHandle(hrec);
7384     MsiViewClose(hview);
7385     MsiCloseHandle(hview);
7386
7387     query = "SELECT * FROM `Table` WHERE `A` = 7";
7388     r = MsiDatabaseOpenView(hdb, query, &hview);
7389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7390     r = MsiViewExecute(hview, 0);
7391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7392
7393     r = MsiViewFetch(hview, &hrec);
7394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7395
7396     r = MsiRecordGetInteger(hrec, 1);
7397     ok(r == 7, "Expected 7, got %d\n", r);
7398
7399     r = MsiRecordGetInteger(hrec, 2);
7400     ok(r == 9, "Expected 9, got %d\n", r);
7401
7402     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7403     r = run_query(hdb, 0, query);
7404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7405
7406     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7408
7409     r = MsiRecordGetInteger(hrec, 1);
7410     ok(r == 7, "Expected 7, got %d\n", r);
7411
7412     r = MsiRecordGetInteger(hrec, 2);
7413     ok(r == 10, "Expected 10, got %d\n", r);
7414
7415     MsiCloseHandle(hrec);
7416     MsiViewClose(hview);
7417     MsiCloseHandle(hview);
7418     MsiCloseHandle(hdb);
7419 }
7420
7421 static BOOL create_storage(LPCSTR name)
7422 {
7423     WCHAR nameW[MAX_PATH];
7424     IStorage *stg;
7425     IStream *stm;
7426     HRESULT hr;
7427     DWORD count;
7428     BOOL res = FALSE;
7429
7430     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7431     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7432                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7433     if (FAILED(hr))
7434         return FALSE;
7435
7436     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7437                                0, 0, &stm);
7438     if (FAILED(hr))
7439         goto done;
7440
7441     hr = IStream_Write(stm, "stgdata", 8, &count);
7442     if (SUCCEEDED(hr))
7443         res = TRUE;
7444
7445 done:
7446     IStream_Release(stm);
7447     IStorage_Release(stg);
7448
7449     return res;
7450 }
7451
7452 static void test_storages_table(void)
7453 {
7454     MSIHANDLE hdb, hview, hrec;
7455     IStorage *stg, *inner;
7456     IStream *stm;
7457     char file[MAX_PATH];
7458     char buf[MAX_PATH];
7459     WCHAR name[MAX_PATH];
7460     LPCSTR query;
7461     HRESULT hr;
7462     DWORD size;
7463     UINT r;
7464
7465     hdb = create_db();
7466     ok(hdb, "failed to create db\n");
7467
7468     r = MsiDatabaseCommit(hdb);
7469     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7470
7471     MsiCloseHandle(hdb);
7472
7473     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
7474     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7475
7476     /* check the column types */
7477     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7478     ok(hrec, "failed to get column info hrecord\n");
7479     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7480     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7481
7482     MsiCloseHandle(hrec);
7483
7484     /* now try the names */
7485     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7486     ok(hrec, "failed to get column info hrecord\n");
7487     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7488     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7489
7490     MsiCloseHandle(hrec);
7491
7492     create_storage("storage.bin");
7493
7494     hrec = MsiCreateRecord(2);
7495     MsiRecordSetString(hrec, 1, "stgname");
7496
7497     r = MsiRecordSetStream(hrec, 2, "storage.bin");
7498     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7499
7500     DeleteFileA("storage.bin");
7501
7502     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7503     r = MsiDatabaseOpenView(hdb, query, &hview);
7504     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7505
7506     r = MsiViewExecute(hview, hrec);
7507     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7508
7509     MsiCloseHandle(hrec);
7510     MsiViewClose(hview);
7511     MsiCloseHandle(hview);
7512
7513     query = "SELECT `Name`, `Data` FROM `_Storages`";
7514     r = MsiDatabaseOpenView(hdb, query, &hview);
7515     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7516
7517     r = MsiViewExecute(hview, 0);
7518     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7519
7520     r = MsiViewFetch(hview, &hrec);
7521     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7522
7523     size = MAX_PATH;
7524     r = MsiRecordGetString(hrec, 1, file, &size);
7525     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7526     ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7527
7528     size = MAX_PATH;
7529     lstrcpyA(buf, "apple");
7530     r = MsiRecordReadStream(hrec, 2, buf, &size);
7531     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7532     ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7533     ok(size == 0, "Expected 0, got %d\n", size);
7534
7535     MsiCloseHandle(hrec);
7536
7537     r = MsiViewFetch(hview, &hrec);
7538     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7539
7540     MsiViewClose(hview);
7541     MsiCloseHandle(hview);
7542
7543     MsiDatabaseCommit(hdb);
7544     MsiCloseHandle(hdb);
7545
7546     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7547     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7548                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7549     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7550     ok(stg != NULL, "Expected non-NULL storage\n");
7551
7552     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7553     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7554                               NULL, 0, &inner);
7555     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7556     ok(inner != NULL, "Expected non-NULL storage\n");
7557
7558     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7559     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7560     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7561     ok(stm != NULL, "Expected non-NULL stream\n");
7562
7563     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7564     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7565     ok(size == 8, "Expected 8, got %d\n", size);
7566     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7567
7568     IStream_Release(stm);
7569     IStorage_Release(inner);
7570
7571     IStorage_Release(stg);
7572     DeleteFileA(msifile);
7573 }
7574
7575 static void test_dbtopackage(void)
7576 {
7577     MSIHANDLE hdb, hpkg;
7578     CHAR package[12], buf[MAX_PATH];
7579     DWORD size;
7580     UINT r;
7581
7582     /* create an empty database, transact mode */
7583     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7584     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7585
7586     set_summary_info(hdb);
7587
7588     r = create_directory_table(hdb);
7589     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7590
7591     r = create_custom_action_table(hdb);
7592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7593
7594     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7596
7597     sprintf(package, "#%u", hdb);
7598     r = MsiOpenPackage(package, &hpkg);
7599     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7600     {
7601         skip("Not enough rights to perform tests\n");
7602         goto error;
7603     }
7604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7605
7606     /* property is not set yet */
7607     size = MAX_PATH;
7608     lstrcpyA(buf, "kiwi");
7609     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7611     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7612     ok(size == 0, "Expected 0, got %d\n", size);
7613
7614     /* run the custom action to set the property */
7615     r = MsiDoAction(hpkg, "SetProp");
7616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7617
7618     /* property is now set */
7619     size = MAX_PATH;
7620     lstrcpyA(buf, "kiwi");
7621     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7623     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7624     ok(size == 5, "Expected 5, got %d\n", size);
7625
7626     MsiCloseHandle(hpkg);
7627
7628     /* reset the package */
7629     r = MsiOpenPackage(package, &hpkg);
7630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7631
7632     /* property is not set anymore */
7633     size = MAX_PATH;
7634     lstrcpyA(buf, "kiwi");
7635     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7637     todo_wine
7638     {
7639         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7640         ok(size == 0, "Expected 0, got %d\n", size);
7641     }
7642
7643     MsiCloseHandle(hdb);
7644     MsiCloseHandle(hpkg);
7645
7646     /* create an empty database, direct mode */
7647     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
7648     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7649
7650     set_summary_info(hdb);
7651
7652     r = create_directory_table(hdb);
7653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7654
7655     r = create_custom_action_table(hdb);
7656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7657
7658     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7660
7661     sprintf(package, "#%u", hdb);
7662     r = MsiOpenPackage(package, &hpkg);
7663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7664
7665     /* property is not set yet */
7666     size = MAX_PATH;
7667     lstrcpyA(buf, "kiwi");
7668     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7670     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7671     ok(size == 0, "Expected 0, got %d\n", size);
7672
7673     /* run the custom action to set the property */
7674     r = MsiDoAction(hpkg, "SetProp");
7675     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7676
7677     /* property is now set */
7678     size = MAX_PATH;
7679     lstrcpyA(buf, "kiwi");
7680     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7682     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7683     ok(size == 5, "Expected 5, got %d\n", size);
7684
7685     MsiCloseHandle(hpkg);
7686
7687     /* reset the package */
7688     r = MsiOpenPackage(package, &hpkg);
7689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7690
7691     /* property is not set anymore */
7692     size = MAX_PATH;
7693     lstrcpyA(buf, "kiwi");
7694     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7696     todo_wine
7697     {
7698         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7699         ok(size == 0, "Expected 0, got %d\n", size);
7700     }
7701
7702     MsiCloseHandle(hpkg);
7703
7704 error:
7705     MsiCloseHandle(hdb);
7706     DeleteFileA(msifile);
7707 }
7708
7709 static void test_droptable(void)
7710 {
7711     MSIHANDLE hdb, hview, hrec;
7712     CHAR buf[MAX_PATH];
7713     LPCSTR query;
7714     DWORD size;
7715     UINT r;
7716
7717     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7719
7720     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7721     r = run_query(hdb, 0, query);
7722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7723
7724     query = "SELECT * FROM `One`";
7725     r = do_query(hdb, query, &hrec);
7726     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7727
7728     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7729     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7730     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7731     r = MsiViewExecute(hview, 0);
7732     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7733
7734     r = MsiViewFetch(hview, &hrec);
7735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7736
7737     size = MAX_PATH;
7738     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7740     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7741
7742     MsiCloseHandle(hrec);
7743     MsiViewClose(hview);
7744     MsiCloseHandle(hview);
7745
7746     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7747     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7749     r = MsiViewExecute(hview, 0);
7750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7751
7752     r = MsiViewFetch(hview, &hrec);
7753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7754
7755     size = MAX_PATH;
7756     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7758     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7759
7760     r = MsiRecordGetInteger(hrec, 2);
7761     ok(r == 1, "Expected 1, got %d\n", r);
7762
7763     size = MAX_PATH;
7764     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7766     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7767
7768     MsiCloseHandle(hrec);
7769
7770     r = MsiViewFetch(hview, &hrec);
7771     ok(r == ERROR_NO_MORE_ITEMS,
7772        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7773
7774     MsiViewClose(hview);
7775     MsiCloseHandle(hview);
7776
7777     query = "DROP `One`";
7778     r = run_query(hdb, 0, query);
7779     ok(r == ERROR_BAD_QUERY_SYNTAX,
7780        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7781
7782     query = "DROP TABLE";
7783     r = run_query(hdb, 0, query);
7784     ok(r == ERROR_BAD_QUERY_SYNTAX,
7785        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7786
7787     query = "DROP TABLE `One`";
7788     hview = 0;
7789     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7791     r = MsiViewExecute(hview, 0);
7792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7793
7794     r = MsiViewFetch(hview, &hrec);
7795     ok(r == ERROR_FUNCTION_FAILED,
7796        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7797
7798     MsiViewClose(hview);
7799     MsiCloseHandle(hview);
7800
7801     query = "SELECT * FROM `IDontExist`";
7802     r = do_query(hdb, query, &hrec);
7803     ok(r == ERROR_BAD_QUERY_SYNTAX,
7804        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7805
7806     query = "SELECT * FROM `One`";
7807     r = do_query(hdb, query, &hrec);
7808     ok(r == ERROR_BAD_QUERY_SYNTAX,
7809        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7810
7811     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7812     r = run_query(hdb, 0, query);
7813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7814
7815     query = "DROP TABLE One";
7816     r = run_query(hdb, 0, query);
7817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7818
7819     query = "SELECT * FROM `One`";
7820     r = do_query(hdb, query, &hrec);
7821     ok(r == ERROR_BAD_QUERY_SYNTAX,
7822        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7823
7824     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7825     r = do_query(hdb, query, &hrec);
7826     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7827
7828     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7829     r = do_query(hdb, query, &hrec);
7830     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7831
7832     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7833     r = run_query(hdb, 0, query);
7834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7835
7836     query = "SELECT * FROM `One`";
7837     r = do_query(hdb, query, &hrec);
7838     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7839
7840     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7841     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7843     r = MsiViewExecute(hview, 0);
7844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7845
7846     r = MsiViewFetch(hview, &hrec);
7847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7848
7849     size = MAX_PATH;
7850     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7852     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7853
7854     MsiCloseHandle(hrec);
7855     MsiViewClose(hview);
7856     MsiCloseHandle(hview);
7857
7858     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7859     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7861     r = MsiViewExecute(hview, 0);
7862     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7863
7864     r = MsiViewFetch(hview, &hrec);
7865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7866
7867     size = MAX_PATH;
7868     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7870     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7871
7872     r = MsiRecordGetInteger(hrec, 2);
7873     ok(r == 1, "Expected 1, got %d\n", r);
7874
7875     size = MAX_PATH;
7876     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7878     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7879
7880     MsiCloseHandle(hrec);
7881
7882     r = MsiViewFetch(hview, &hrec);
7883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7884
7885     size = MAX_PATH;
7886     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7887     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7888     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7889
7890     r = MsiRecordGetInteger(hrec, 2);
7891     ok(r == 2, "Expected 2, got %d\n", r);
7892
7893     size = MAX_PATH;
7894     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7896     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7897
7898     MsiCloseHandle(hrec);
7899
7900     r = MsiViewFetch(hview, &hrec);
7901     ok(r == ERROR_NO_MORE_ITEMS,
7902        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7903
7904     MsiViewClose(hview);
7905     MsiCloseHandle(hview);
7906
7907     query = "DROP TABLE One";
7908     r = run_query(hdb, 0, query);
7909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7910
7911     query = "SELECT * FROM `One`";
7912     r = do_query(hdb, query, &hrec);
7913     ok(r == ERROR_BAD_QUERY_SYNTAX,
7914        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7915
7916     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7917     r = do_query(hdb, query, &hrec);
7918     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7919
7920     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7921     r = do_query(hdb, query, &hrec);
7922     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7923
7924     MsiCloseHandle(hdb);
7925     DeleteFileA(msifile);
7926 }
7927
7928 static void test_dbmerge(void)
7929 {
7930     MSIHANDLE hdb, href, hview, hrec;
7931     CHAR buf[MAX_PATH];
7932     LPCSTR query;
7933     DWORD size;
7934     UINT r;
7935
7936     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7938
7939     r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
7940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7941
7942     /* hDatabase is invalid */
7943     r = MsiDatabaseMergeA(0, href, "MergeErrors");
7944     ok(r == ERROR_INVALID_HANDLE,
7945        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7946
7947     /* hDatabaseMerge is invalid */
7948     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7949     ok(r == ERROR_INVALID_HANDLE,
7950        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7951
7952     /* szTableName is NULL */
7953     r = MsiDatabaseMergeA(hdb, href, NULL);
7954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7955
7956     /* szTableName is empty */
7957     r = MsiDatabaseMergeA(hdb, href, "");
7958     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7959
7960     /* both DBs empty, szTableName is valid */
7961     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7963
7964     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7965     r = run_query(hdb, 0, query);
7966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7967
7968     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7969     r = run_query(href, 0, query);
7970     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7971
7972     /* column types don't match */
7973     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7974     ok(r == ERROR_DATATYPE_MISMATCH,
7975        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7976
7977     /* nothing in MergeErrors */
7978     query = "SELECT * FROM `MergeErrors`";
7979     r = do_query(hdb, query, &hrec);
7980     ok(r == ERROR_BAD_QUERY_SYNTAX,
7981        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7982
7983     query = "DROP TABLE `One`";
7984     r = run_query(hdb, 0, query);
7985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7986
7987     query = "DROP TABLE `One`";
7988     r = run_query(href, 0, query);
7989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7990
7991     query = "CREATE TABLE `One` ( "
7992         "`A` CHAR(72), "
7993         "`B` CHAR(56), "
7994         "`C` CHAR(64) LOCALIZABLE, "
7995         "`D` LONGCHAR, "
7996         "`E` CHAR(72) NOT NULL, "
7997         "`F` CHAR(56) NOT NULL, "
7998         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7999         "`H` LONGCHAR NOT NULL "
8000         "PRIMARY KEY `A` )";
8001     r = run_query(hdb, 0, query);
8002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8003
8004     query = "CREATE TABLE `One` ( "
8005         "`A` CHAR(64), "
8006         "`B` CHAR(64), "
8007         "`C` CHAR(64), "
8008         "`D` CHAR(64), "
8009         "`E` CHAR(64) NOT NULL, "
8010         "`F` CHAR(64) NOT NULL, "
8011         "`G` CHAR(64) NOT NULL, "
8012         "`H` CHAR(64) NOT NULL "
8013         "PRIMARY KEY `A` )";
8014     r = run_query(href, 0, query);
8015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8016
8017     /* column sting types don't match exactly */
8018     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8019     ok(r == ERROR_SUCCESS,
8020        "Expected ERROR_SUCCESS, got %d\n", r);
8021
8022     /* nothing in MergeErrors */
8023     query = "SELECT * FROM `MergeErrors`";
8024     r = do_query(hdb, query, &hrec);
8025     ok(r == ERROR_BAD_QUERY_SYNTAX,
8026        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8027
8028     query = "DROP TABLE `One`";
8029     r = run_query(hdb, 0, query);
8030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8031
8032     query = "DROP TABLE `One`";
8033     r = run_query(href, 0, query);
8034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8035
8036     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8037     r = run_query(hdb, 0, query);
8038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8039
8040     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
8041     r = run_query(href, 0, query);
8042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8043
8044     /* column names don't match */
8045     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8046     ok(r == ERROR_DATATYPE_MISMATCH,
8047        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8048
8049     /* nothing in MergeErrors */
8050     query = "SELECT * FROM `MergeErrors`";
8051     r = do_query(hdb, query, &hrec);
8052     ok(r == ERROR_BAD_QUERY_SYNTAX,
8053        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8054
8055     query = "DROP TABLE `One`";
8056     r = run_query(hdb, 0, query);
8057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8058
8059     query = "DROP TABLE `One`";
8060     r = run_query(href, 0, query);
8061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8062
8063     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8064     r = run_query(hdb, 0, query);
8065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8066
8067     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
8068     r = run_query(href, 0, query);
8069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8070
8071     /* primary keys don't match */
8072     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8073     ok(r == ERROR_DATATYPE_MISMATCH,
8074        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8075
8076     /* nothing in MergeErrors */
8077     query = "SELECT * FROM `MergeErrors`";
8078     r = do_query(hdb, query, &hrec);
8079     ok(r == ERROR_BAD_QUERY_SYNTAX,
8080        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8081
8082     query = "DROP TABLE `One`";
8083     r = run_query(hdb, 0, query);
8084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8085
8086     query = "DROP TABLE `One`";
8087     r = run_query(href, 0, query);
8088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8089
8090     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8091     r = run_query(hdb, 0, query);
8092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8093
8094     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
8095     r = run_query(href, 0, query);
8096     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8097
8098     /* number of primary keys doesn't match */
8099     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8100     ok(r == ERROR_DATATYPE_MISMATCH,
8101        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8102
8103     /* nothing in MergeErrors */
8104     query = "SELECT * FROM `MergeErrors`";
8105     r = do_query(hdb, query, &hrec);
8106     ok(r == ERROR_BAD_QUERY_SYNTAX,
8107        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8108
8109     query = "DROP TABLE `One`";
8110     r = run_query(hdb, 0, query);
8111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8112
8113     query = "DROP TABLE `One`";
8114     r = run_query(href, 0, query);
8115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8116
8117     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8118     r = run_query(hdb, 0, query);
8119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8120
8121     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8122     r = run_query(href, 0, query);
8123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8124
8125     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8126     r = run_query(href, 0, query);
8127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8128
8129     /* number of columns doesn't match */
8130     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8132
8133     query = "SELECT * FROM `One`";
8134     r = do_query(hdb, query, &hrec);
8135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8136
8137     r = MsiRecordGetInteger(hrec, 1);
8138     ok(r == 1, "Expected 1, got %d\n", r);
8139
8140     r = MsiRecordGetInteger(hrec, 2);
8141     ok(r == 2, "Expected 2, got %d\n", r);
8142
8143     r = MsiRecordGetInteger(hrec, 3);
8144     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8145
8146     MsiCloseHandle(hrec);
8147
8148     /* nothing in MergeErrors */
8149     query = "SELECT * FROM `MergeErrors`";
8150     r = do_query(hdb, query, &hrec);
8151     ok(r == ERROR_BAD_QUERY_SYNTAX,
8152        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8153
8154     query = "DROP TABLE `One`";
8155     r = run_query(hdb, 0, query);
8156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8157
8158     query = "DROP TABLE `One`";
8159     r = run_query(href, 0, query);
8160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8161
8162     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8163     r = run_query(hdb, 0, query);
8164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8165
8166     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8167     r = run_query(href, 0, query);
8168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8169
8170     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8171     r = run_query(href, 0, query);
8172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8173
8174     /* number of columns doesn't match */
8175     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8177
8178     query = "SELECT * FROM `One`";
8179     r = do_query(hdb, query, &hrec);
8180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8181
8182     r = MsiRecordGetInteger(hrec, 1);
8183     ok(r == 1, "Expected 1, got %d\n", r);
8184
8185     r = MsiRecordGetInteger(hrec, 2);
8186     ok(r == 2, "Expected 2, got %d\n", r);
8187
8188     r = MsiRecordGetInteger(hrec, 3);
8189     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8190
8191     MsiCloseHandle(hrec);
8192
8193     /* nothing in MergeErrors */
8194     query = "SELECT * FROM `MergeErrors`";
8195     r = do_query(hdb, query, &hrec);
8196     ok(r == ERROR_BAD_QUERY_SYNTAX,
8197        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8198
8199     query = "DROP TABLE `One`";
8200     r = run_query(hdb, 0, query);
8201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8202
8203     query = "DROP TABLE `One`";
8204     r = run_query(href, 0, query);
8205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8206
8207     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8208     r = run_query(hdb, 0, query);
8209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8210
8211     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
8212     r = run_query(hdb, 0, query);
8213     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8214
8215     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8216     r = run_query(hdb, 0, query);
8217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8218
8219     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8220     r = run_query(href, 0, query);
8221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8222
8223     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8224     r = run_query(href, 0, query);
8225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8226
8227     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
8228     r = run_query(href, 0, query);
8229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8230
8231     /* primary keys match, rows do not */
8232     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8233     ok(r == ERROR_FUNCTION_FAILED,
8234        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8235
8236     /* nothing in MergeErrors */
8237     query = "SELECT * FROM `MergeErrors`";
8238     r = do_query(hdb, query, &hrec);
8239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8240
8241     size = MAX_PATH;
8242     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8244     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8245
8246     r = MsiRecordGetInteger(hrec, 2);
8247     ok(r == 2, "Expected 2, got %d\n", r);
8248
8249     MsiCloseHandle(hrec);
8250
8251     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8253
8254     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8255     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8256
8257     size = MAX_PATH;
8258     r = MsiRecordGetString(hrec, 1, buf, &size);
8259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8260     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8261
8262     size = MAX_PATH;
8263     r = MsiRecordGetString(hrec, 2, buf, &size);
8264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8265     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8266        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8267
8268     MsiCloseHandle(hrec);
8269
8270     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8272
8273     size = MAX_PATH;
8274     r = MsiRecordGetString(hrec, 1, buf, &size);
8275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8276     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8277
8278     size = MAX_PATH;
8279     r = MsiRecordGetString(hrec, 2, buf, &size);
8280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8281     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8282
8283     MsiCloseHandle(hrec);
8284     MsiViewClose(hview);
8285     MsiCloseHandle(hview);
8286
8287     query = "DROP TABLE `MergeErrors`";
8288     r = run_query(hdb, 0, query);
8289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8290
8291     query = "DROP TABLE `One`";
8292     r = run_query(hdb, 0, query);
8293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8294
8295     query = "DROP TABLE `One`";
8296     r = run_query(href, 0, query);
8297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8298
8299     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8300     r = run_query(href, 0, query);
8301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8302
8303     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8304     r = run_query(href, 0, query);
8305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8306
8307     /* table from merged database is not in target database */
8308     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8310
8311     query = "SELECT * FROM `One`";
8312     r = do_query(hdb, query, &hrec);
8313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8314
8315     r = MsiRecordGetInteger(hrec, 1);
8316     ok(r == 1, "Expected 1, got %d\n", r);
8317
8318     size = MAX_PATH;
8319     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8321     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8322
8323     MsiCloseHandle(hrec);
8324
8325     /* nothing in MergeErrors */
8326     query = "SELECT * FROM `MergeErrors`";
8327     r = do_query(hdb, query, &hrec);
8328     ok(r == ERROR_BAD_QUERY_SYNTAX,
8329        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8330
8331     query = "DROP TABLE `One`";
8332     r = run_query(hdb, 0, query);
8333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8334
8335     query = "DROP TABLE `One`";
8336     r = run_query(href, 0, query);
8337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8338
8339     query = "CREATE TABLE `One` ( "
8340             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8341     r = run_query(hdb, 0, query);
8342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8343
8344     query = "CREATE TABLE `One` ( "
8345             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8346     r = run_query(href, 0, query);
8347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8348
8349     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8350     r = run_query(href, 0, query);
8351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8352
8353     /* primary key is string */
8354     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8356
8357     query = "SELECT * FROM `One`";
8358     r = do_query(hdb, query, &hrec);
8359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8360
8361     size = MAX_PATH;
8362     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8364     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8365
8366     r = MsiRecordGetInteger(hrec, 2);
8367     ok(r == 1, "Expected 1, got %d\n", r);
8368
8369     MsiCloseHandle(hrec);
8370
8371     /* nothing in MergeErrors */
8372     query = "SELECT * FROM `MergeErrors`";
8373     r = do_query(hdb, query, &hrec);
8374     ok(r == ERROR_BAD_QUERY_SYNTAX,
8375        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8376
8377     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8378
8379     GetCurrentDirectoryA(MAX_PATH, buf);
8380     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8382
8383     query = "DROP TABLE `One`";
8384     r = run_query(hdb, 0, query);
8385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8386
8387     query = "DROP TABLE `One`";
8388     r = run_query(href, 0, query);
8389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8390
8391     query = "CREATE TABLE `One` ( "
8392             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8393     r = run_query(hdb, 0, query);
8394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8395
8396     query = "CREATE TABLE `One` ( "
8397             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8398     r = run_query(href, 0, query);
8399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8400
8401     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8402     r = run_query(href, 0, query);
8403     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8404
8405     /* code page does not match */
8406     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8408
8409     query = "SELECT * FROM `One`";
8410     r = do_query(hdb, query, &hrec);
8411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8412
8413     r = MsiRecordGetInteger(hrec, 1);
8414     ok(r == 1, "Expected 1, got %d\n", r);
8415
8416     size = MAX_PATH;
8417     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8419     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8420
8421     MsiCloseHandle(hrec);
8422
8423     /* nothing in MergeErrors */
8424     query = "SELECT * FROM `MergeErrors`";
8425     r = do_query(hdb, query, &hrec);
8426     ok(r == ERROR_BAD_QUERY_SYNTAX,
8427        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8428
8429     query = "DROP TABLE `One`";
8430     r = run_query(hdb, 0, query);
8431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8432
8433     query = "DROP TABLE `One`";
8434     r = run_query(href, 0, query);
8435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8436
8437     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8438     r = run_query(hdb, 0, query);
8439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8440
8441     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8442     r = run_query(href, 0, query);
8443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8444
8445     create_file("binary.dat");
8446     hrec = MsiCreateRecord(1);
8447     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8448
8449     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8450     r = run_query(href, hrec, query);
8451     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8452
8453     MsiCloseHandle(hrec);
8454
8455     /* binary data to merge */
8456     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8458
8459     query = "SELECT * FROM `One`";
8460     r = do_query(hdb, query, &hrec);
8461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8462
8463     r = MsiRecordGetInteger(hrec, 1);
8464     ok(r == 1, "Expected 1, got %d\n", r);
8465
8466     size = MAX_PATH;
8467     ZeroMemory(buf, MAX_PATH);
8468     r = MsiRecordReadStream(hrec, 2, buf, &size);
8469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8470     ok(!lstrcmpA(buf, "binary.dat\n"),
8471        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8472
8473     MsiCloseHandle(hrec);
8474
8475     /* nothing in MergeErrors */
8476     query = "SELECT * FROM `MergeErrors`";
8477     r = do_query(hdb, query, &hrec);
8478     ok(r == ERROR_BAD_QUERY_SYNTAX,
8479        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8480
8481     query = "DROP TABLE `One`";
8482     r = run_query(hdb, 0, query);
8483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8484
8485     query = "DROP TABLE `One`";
8486     r = run_query(href, 0, query);
8487     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8488
8489     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8490     r = run_query(hdb, 0, query);
8491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8492     r = run_query(href, 0, query);
8493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8494
8495     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8496     r = run_query(href, 0, query);
8497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8498
8499     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8500     r = run_query(href, 0, query);
8501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8502
8503     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8505
8506     query = "SELECT * FROM `One`";
8507     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8509     r = MsiViewExecute(hview, 0);
8510     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8511
8512     r = MsiViewFetch(hview, &hrec);
8513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8514
8515     r = MsiRecordGetInteger(hrec, 1);
8516     ok(r == 1, "Expected 1, got %d\n", r);
8517
8518     size = MAX_PATH;
8519     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8521     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8522
8523     MsiCloseHandle(hrec);
8524
8525     r = MsiViewFetch(hview, &hrec);
8526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8527
8528     r = MsiRecordGetInteger(hrec, 1);
8529     ok(r == 2, "Expected 2, got %d\n", r);
8530
8531     size = MAX_PATH;
8532     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8534     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8535
8536     MsiCloseHandle(hrec);
8537
8538     r = MsiViewFetch(hview, &hrec);
8539     ok(r == ERROR_NO_MORE_ITEMS,
8540        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8541
8542     MsiViewClose(hview);
8543     MsiCloseHandle(hview);
8544
8545     MsiCloseHandle(hdb);
8546     MsiCloseHandle(href);
8547     DeleteFileA(msifile);
8548     DeleteFileA("refdb.msi");
8549     DeleteFileA("codepage.idt");
8550     DeleteFileA("binary.dat");
8551 }
8552
8553 static void test_select_with_tablenames(void)
8554 {
8555     MSIHANDLE hdb, view, rec;
8556     LPCSTR query;
8557     UINT r;
8558     int i;
8559
8560     int vals[4][2] = {
8561         {1,12},
8562         {4,12},
8563         {1,15},
8564         {4,15}};
8565
8566     hdb = create_db();
8567     ok(hdb, "failed to create db\n");
8568
8569     /* Build a pair of tables with the same column names, but unique data */
8570     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8571     r = run_query(hdb, 0, query);
8572     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8573
8574     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8575     r = run_query(hdb, 0, query);
8576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8577
8578     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8579     r = run_query(hdb, 0, query);
8580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8581
8582     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8583     r = run_query(hdb, 0, query);
8584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8585
8586     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8587     r = run_query(hdb, 0, query);
8588     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8589
8590     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8591     r = run_query(hdb, 0, query);
8592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8593
8594
8595     /* Test that selection based on prefixing the column with the table
8596      * actually selects the right data */
8597
8598     query = "SELECT T1.A, T2.B FROM T1,T2";
8599     r = MsiDatabaseOpenView(hdb, query, &view);
8600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8601     r = MsiViewExecute(view, 0);
8602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8603
8604     for (i = 0; i < 4; i++)
8605     {
8606         r = MsiViewFetch(view, &rec);
8607         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8608
8609         r = MsiRecordGetInteger(rec, 1);
8610         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8611
8612         r = MsiRecordGetInteger(rec, 2);
8613         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8614
8615         MsiCloseHandle(rec);
8616     }
8617
8618     r = MsiViewFetch(view, &rec);
8619     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8620
8621     MsiViewClose(view);
8622     MsiCloseHandle(view);
8623     MsiCloseHandle(hdb);
8624     DeleteFileA(msifile);
8625 }
8626
8627 static const UINT ordervals[6][3] =
8628 {
8629     { MSI_NULL_INTEGER, 12, 13 },
8630     { 1, 2, 3 },
8631     { 6, 4, 5 },
8632     { 8, 9, 7 },
8633     { 10, 11, MSI_NULL_INTEGER },
8634     { 14, MSI_NULL_INTEGER, 15 }
8635 };
8636
8637 static void test_insertorder(void)
8638 {
8639     MSIHANDLE hdb, view, rec;
8640     LPCSTR query;
8641     UINT r;
8642     int i;
8643
8644     hdb = create_db();
8645     ok(hdb, "failed to create db\n");
8646
8647     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8648     r = run_query(hdb, 0, query);
8649     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8650
8651     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8652     r = run_query(hdb, 0, query);
8653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8654
8655     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8656     r = run_query(hdb, 0, query);
8657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8658
8659     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8660     r = run_query(hdb, 0, query);
8661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8662
8663     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8664     r = run_query(hdb, 0, query);
8665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8666
8667     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8668     r = run_query(hdb, 0, query);
8669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8670
8671     /* fails because the primary key already
8672      * has an MSI_NULL_INTEGER value set above
8673      */
8674     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8675     r = run_query(hdb, 0, query);
8676     ok(r == ERROR_FUNCTION_FAILED,
8677        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8678
8679     /* replicate the error where primary key is set twice */
8680     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8681     r = run_query(hdb, 0, query);
8682     ok(r == ERROR_FUNCTION_FAILED,
8683        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8684
8685     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8686     r = run_query(hdb, 0, query);
8687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8688
8689     query = "INSERT INTO `T` VALUES ( 16 )";
8690     r = run_query(hdb, 0, query);
8691     ok(r == ERROR_BAD_QUERY_SYNTAX,
8692        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8693
8694     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8695     r = run_query(hdb, 0, query);
8696     ok(r == ERROR_BAD_QUERY_SYNTAX,
8697        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8698
8699     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8700     r = run_query(hdb, 0, query);
8701     ok(r == ERROR_BAD_QUERY_SYNTAX,
8702        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8703
8704     query = "SELECT * FROM `T`";
8705     r = MsiDatabaseOpenView(hdb, query, &view);
8706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8707     r = MsiViewExecute(view, 0);
8708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8709
8710     for (i = 0; i < 6; i++)
8711     {
8712         r = MsiViewFetch(view, &rec);
8713         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8714
8715         r = MsiRecordGetInteger(rec, 1);
8716         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8717
8718         r = MsiRecordGetInteger(rec, 2);
8719         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8720
8721         r = MsiRecordGetInteger(rec, 3);
8722         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8723
8724         MsiCloseHandle(rec);
8725     }
8726
8727     r = MsiViewFetch(view, &rec);
8728     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8729
8730     MsiViewClose(view);
8731     MsiCloseHandle(view);
8732
8733     query = "DELETE FROM `T` WHERE `A` IS NULL";
8734     r = run_query(hdb, 0, query);
8735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8736
8737     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8738     r = run_query(hdb, 0, query);
8739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8740
8741     query = "SELECT * FROM `T`";
8742     r = MsiDatabaseOpenView(hdb, query, &view);
8743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8744     r = MsiViewExecute(view, 0);
8745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8746
8747     for (i = 0; i < 6; i++)
8748     {
8749         r = MsiViewFetch(view, &rec);
8750         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8751
8752         r = MsiRecordGetInteger(rec, 1);
8753         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8754
8755         r = MsiRecordGetInteger(rec, 2);
8756         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8757
8758         r = MsiRecordGetInteger(rec, 3);
8759         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8760
8761         MsiCloseHandle(rec);
8762     }
8763
8764     r = MsiViewFetch(view, &rec);
8765     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8766
8767     MsiViewClose(view);
8768     MsiCloseHandle(view);
8769     MsiCloseHandle(hdb);
8770     DeleteFileA(msifile);
8771 }
8772
8773 static void test_columnorder(void)
8774 {
8775     MSIHANDLE hdb, view, rec;
8776     char buf[MAX_PATH];
8777     LPCSTR query;
8778     DWORD sz;
8779     UINT r;
8780
8781     hdb = create_db();
8782     ok(hdb, "failed to create db\n");
8783
8784     /* Each column is a slot:
8785      * ---------------------
8786      * | B | C | A | E | D |
8787      * ---------------------
8788      *
8789      * When a column is selected as a primary key,
8790      * the column occupying the nth primary key slot is swapped
8791      * with the current position of the primary key in question:
8792      *
8793      * set primary key `D`
8794      * ---------------------    ---------------------
8795      * | B | C | A | E | D | -> | D | C | A | E | B |
8796      * ---------------------    ---------------------
8797      *
8798      * set primary key `E`
8799      * ---------------------    ---------------------
8800      * | D | C | A | E | B | -> | D | E | A | C | B |
8801      * ---------------------    ---------------------
8802      */
8803
8804     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8805             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8806             "PRIMARY KEY `D`, `E`)";
8807     r = run_query(hdb, 0, query);
8808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8809
8810     query = "SELECT * FROM `T`";
8811     r = MsiDatabaseOpenView(hdb, query, &view);
8812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8813
8814     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8816
8817     sz = MAX_PATH;
8818     lstrcpyA(buf, "kiwi");
8819     r = MsiRecordGetString(rec, 1, buf, &sz);
8820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8821     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8822
8823     sz = MAX_PATH;
8824     lstrcpyA(buf, "kiwi");
8825     r = MsiRecordGetString(rec, 2, buf, &sz);
8826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8827     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8828
8829     sz = MAX_PATH;
8830     lstrcpyA(buf, "kiwi");
8831     r = MsiRecordGetString(rec, 3, buf, &sz);
8832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8833     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8834
8835     sz = MAX_PATH;
8836     lstrcpyA(buf, "kiwi");
8837     r = MsiRecordGetString(rec, 4, buf, &sz);
8838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8839     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8840
8841     sz = MAX_PATH;
8842     lstrcpyA(buf, "kiwi");
8843     r = MsiRecordGetString(rec, 5, buf, &sz);
8844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8845     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8846
8847     MsiCloseHandle(rec);
8848
8849     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8851
8852     sz = MAX_PATH;
8853     lstrcpyA(buf, "kiwi");
8854     r = MsiRecordGetString(rec, 1, buf, &sz);
8855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8856     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8857
8858     sz = MAX_PATH;
8859     lstrcpyA(buf, "kiwi");
8860     r = MsiRecordGetString(rec, 2, buf, &sz);
8861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8862     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8863
8864     sz = MAX_PATH;
8865     lstrcpyA(buf, "kiwi");
8866     r = MsiRecordGetString(rec, 3, buf, &sz);
8867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8868     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8869
8870     sz = MAX_PATH;
8871     lstrcpyA(buf, "kiwi");
8872     r = MsiRecordGetString(rec, 4, buf, &sz);
8873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8874     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8875
8876     sz = MAX_PATH;
8877     lstrcpyA(buf, "kiwi");
8878     r = MsiRecordGetString(rec, 5, buf, &sz);
8879     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8880     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8881
8882     MsiCloseHandle(rec);
8883     MsiViewClose(view);
8884     MsiCloseHandle(view);
8885
8886     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8887             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8888     r = run_query(hdb, 0, query);
8889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8890
8891     query = "SELECT * FROM `T`";
8892     r = do_query(hdb, query, &rec);
8893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8894
8895     sz = MAX_PATH;
8896     lstrcpyA(buf, "kiwi");
8897     r = MsiRecordGetString(rec, 1, buf, &sz);
8898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8899     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8900
8901     r = MsiRecordGetInteger(rec, 2);
8902     ok(r == 3, "Expected 3, got %d\n", r);
8903
8904     sz = MAX_PATH;
8905     lstrcpyA(buf, "kiwi");
8906     r = MsiRecordGetString(rec, 3, buf, &sz);
8907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8908     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8909
8910     r = MsiRecordGetInteger(rec, 4);
8911     ok(r == 2, "Expected 2, got %d\n", r);
8912
8913     r = MsiRecordGetInteger(rec, 5);
8914     ok(r == 1, "Expected 1, got %d\n", r);
8915
8916     MsiCloseHandle(rec);
8917
8918     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8919     r = MsiDatabaseOpenView(hdb, query, &view);
8920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8921     r = MsiViewExecute(view, 0);
8922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8923
8924     r = MsiViewFetch(view, &rec);
8925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8926
8927     sz = MAX_PATH;
8928     lstrcpyA(buf, "kiwi");
8929     r = MsiRecordGetString(rec, 1, buf, &sz);
8930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8931     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8932
8933     r = MsiRecordGetInteger(rec, 2);
8934     ok(r == 1, "Expected 1, got %d\n", r);
8935
8936     sz = MAX_PATH;
8937     lstrcpyA(buf, "kiwi");
8938     r = MsiRecordGetString(rec, 3, buf, &sz);
8939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8940     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8941
8942     MsiCloseHandle(rec);
8943
8944     r = MsiViewFetch(view, &rec);
8945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8946
8947     sz = MAX_PATH;
8948     lstrcpyA(buf, "kiwi");
8949     r = MsiRecordGetString(rec, 1, buf, &sz);
8950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8951     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8952
8953     r = MsiRecordGetInteger(rec, 2);
8954     ok(r == 2, "Expected 2, got %d\n", r);
8955
8956     sz = MAX_PATH;
8957     lstrcpyA(buf, "kiwi");
8958     r = MsiRecordGetString(rec, 3, buf, &sz);
8959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8960     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8961
8962     MsiCloseHandle(rec);
8963
8964     r = MsiViewFetch(view, &rec);
8965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8966
8967     sz = MAX_PATH;
8968     lstrcpyA(buf, "kiwi");
8969     r = MsiRecordGetString(rec, 1, buf, &sz);
8970     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8971     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8972
8973     r = MsiRecordGetInteger(rec, 2);
8974     ok(r == 3, "Expected 3, got %d\n", r);
8975
8976     sz = MAX_PATH;
8977     lstrcpyA(buf, "kiwi");
8978     r = MsiRecordGetString(rec, 3, buf, &sz);
8979     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8980     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8981
8982     MsiCloseHandle(rec);
8983
8984     r = MsiViewFetch(view, &rec);
8985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8986
8987     sz = MAX_PATH;
8988     lstrcpyA(buf, "kiwi");
8989     r = MsiRecordGetString(rec, 1, buf, &sz);
8990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8991     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8992
8993     r = MsiRecordGetInteger(rec, 2);
8994     ok(r == 4, "Expected 4, got %d\n", r);
8995
8996     sz = MAX_PATH;
8997     lstrcpyA(buf, "kiwi");
8998     r = MsiRecordGetString(rec, 3, buf, &sz);
8999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9000     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9001
9002     MsiCloseHandle(rec);
9003
9004     r = MsiViewFetch(view, &rec);
9005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9006
9007     sz = MAX_PATH;
9008     lstrcpyA(buf, "kiwi");
9009     r = MsiRecordGetString(rec, 1, buf, &sz);
9010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9011     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9012
9013     r = MsiRecordGetInteger(rec, 2);
9014     ok(r == 5, "Expected 5, got %d\n", r);
9015
9016     sz = MAX_PATH;
9017     lstrcpyA(buf, "kiwi");
9018     r = MsiRecordGetString(rec, 3, buf, &sz);
9019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9020     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9021
9022     MsiCloseHandle(rec);
9023
9024     r = MsiViewFetch(view, &rec);
9025     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9026
9027     MsiViewClose(view);
9028     MsiCloseHandle(view);
9029
9030     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
9031             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
9032             "PRIMARY KEY `C`, `A`, `D`)";
9033     r = run_query(hdb, 0, query);
9034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9035
9036     query = "SELECT * FROM `Z`";
9037     r = MsiDatabaseOpenView(hdb, query, &view);
9038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9039
9040     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
9041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9042
9043     sz = MAX_PATH;
9044     lstrcpyA(buf, "kiwi");
9045     r = MsiRecordGetString(rec, 1, buf, &sz);
9046     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9047     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9048
9049     sz = MAX_PATH;
9050     lstrcpyA(buf, "kiwi");
9051     r = MsiRecordGetString(rec, 2, buf, &sz);
9052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9053     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
9054
9055     sz = MAX_PATH;
9056     lstrcpyA(buf, "kiwi");
9057     r = MsiRecordGetString(rec, 3, buf, &sz);
9058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9059     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
9060
9061     sz = MAX_PATH;
9062     lstrcpyA(buf, "kiwi");
9063     r = MsiRecordGetString(rec, 4, buf, &sz);
9064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9065     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
9066
9067     sz = MAX_PATH;
9068     lstrcpyA(buf, "kiwi");
9069     r = MsiRecordGetString(rec, 5, buf, &sz);
9070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9071     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9072
9073     MsiCloseHandle(rec);
9074
9075     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
9076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9077
9078     sz = MAX_PATH;
9079     lstrcpyA(buf, "kiwi");
9080     r = MsiRecordGetString(rec, 1, buf, &sz);
9081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9082     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9083
9084     sz = MAX_PATH;
9085     lstrcpyA(buf, "kiwi");
9086     r = MsiRecordGetString(rec, 2, buf, &sz);
9087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9088     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9089
9090     sz = MAX_PATH;
9091     lstrcpyA(buf, "kiwi");
9092     r = MsiRecordGetString(rec, 3, buf, &sz);
9093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9094     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9095
9096     sz = MAX_PATH;
9097     lstrcpyA(buf, "kiwi");
9098     r = MsiRecordGetString(rec, 4, buf, &sz);
9099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9100     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9101
9102     sz = MAX_PATH;
9103     lstrcpyA(buf, "kiwi");
9104     r = MsiRecordGetString(rec, 5, buf, &sz);
9105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9106     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9107
9108     MsiCloseHandle(rec);
9109     MsiViewClose(view);
9110     MsiCloseHandle(view);
9111
9112     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
9113             "VALUES ( 1, 2, 'a', 3, 'bc' )";
9114     r = run_query(hdb, 0, query);
9115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9116
9117     query = "SELECT * FROM `Z`";
9118     r = do_query(hdb, query, &rec);
9119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9120
9121     r = MsiRecordGetInteger(rec, 1);
9122     ok(r == 2, "Expected 2, got %d\n", r);
9123
9124     sz = MAX_PATH;
9125     lstrcpyA(buf, "kiwi");
9126     r = MsiRecordGetString(rec, 2, buf, &sz);
9127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9128     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
9129
9130     sz = MAX_PATH;
9131     lstrcpyA(buf, "kiwi");
9132     r = MsiRecordGetString(rec, 3, buf, &sz);
9133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9134     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
9135
9136     r = MsiRecordGetInteger(rec, 4);
9137     ok(r == 3, "Expected 3, got %d\n", r);
9138
9139     r = MsiRecordGetInteger(rec, 5);
9140     ok(r == 1, "Expected 1, got %d\n", r);
9141
9142     MsiCloseHandle(rec);
9143
9144     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
9145     r = MsiDatabaseOpenView(hdb, query, &view);
9146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9147     r = MsiViewExecute(view, 0);
9148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9149
9150     r = MsiViewFetch(view, &rec);
9151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9152
9153     sz = MAX_PATH;
9154     lstrcpyA(buf, "kiwi");
9155     r = MsiRecordGetString(rec, 1, buf, &sz);
9156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9157     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9158
9159     r = MsiRecordGetInteger(rec, 2);
9160     ok(r == 1, "Expected 1, got %d\n", r);
9161
9162     sz = MAX_PATH;
9163     lstrcpyA(buf, "kiwi");
9164     r = MsiRecordGetString(rec, 3, buf, &sz);
9165     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9166     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9167
9168     MsiCloseHandle(rec);
9169
9170     r = MsiViewFetch(view, &rec);
9171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9172
9173     sz = MAX_PATH;
9174     lstrcpyA(buf, "kiwi");
9175     r = MsiRecordGetString(rec, 1, buf, &sz);
9176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9177     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9178
9179     r = MsiRecordGetInteger(rec, 2);
9180     ok(r == 2, "Expected 2, got %d\n", r);
9181
9182     sz = MAX_PATH;
9183     lstrcpyA(buf, "kiwi");
9184     r = MsiRecordGetString(rec, 3, buf, &sz);
9185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9186     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9187
9188     MsiCloseHandle(rec);
9189
9190     r = MsiViewFetch(view, &rec);
9191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9192
9193     sz = MAX_PATH;
9194     lstrcpyA(buf, "kiwi");
9195     r = MsiRecordGetString(rec, 1, buf, &sz);
9196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9197     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9198
9199     r = MsiRecordGetInteger(rec, 2);
9200     ok(r == 3, "Expected 3, got %d\n", r);
9201
9202     sz = MAX_PATH;
9203     lstrcpyA(buf, "kiwi");
9204     r = MsiRecordGetString(rec, 3, buf, &sz);
9205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9206     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9207
9208     MsiCloseHandle(rec);
9209
9210     r = MsiViewFetch(view, &rec);
9211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9212
9213     sz = MAX_PATH;
9214     lstrcpyA(buf, "kiwi");
9215     r = MsiRecordGetString(rec, 1, buf, &sz);
9216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9217     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9218
9219     r = MsiRecordGetInteger(rec, 2);
9220     ok(r == 4, "Expected 4, got %d\n", r);
9221
9222     sz = MAX_PATH;
9223     lstrcpyA(buf, "kiwi");
9224     r = MsiRecordGetString(rec, 3, buf, &sz);
9225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9226     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9227
9228     MsiCloseHandle(rec);
9229
9230     r = MsiViewFetch(view, &rec);
9231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9232
9233     sz = MAX_PATH;
9234     lstrcpyA(buf, "kiwi");
9235     r = MsiRecordGetString(rec, 1, buf, &sz);
9236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9237     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9238
9239     r = MsiRecordGetInteger(rec, 2);
9240     ok(r == 5, "Expected 5, got %d\n", r);
9241
9242     sz = MAX_PATH;
9243     lstrcpyA(buf, "kiwi");
9244     r = MsiRecordGetString(rec, 3, buf, &sz);
9245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9246     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9247
9248     MsiCloseHandle(rec);
9249
9250     r = MsiViewFetch(view, &rec);
9251     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9252
9253     MsiViewClose(view);
9254     MsiCloseHandle(view);
9255
9256     MsiCloseHandle(hdb);
9257     DeleteFileA(msifile);
9258 }
9259
9260 static void test_createtable(void)
9261 {
9262     MSIHANDLE hdb, htab = 0, hrec = 0;
9263     LPCSTR query;
9264     UINT res;
9265     DWORD size;
9266     char buffer[0x20];
9267
9268     hdb = create_db();
9269     ok(hdb, "failed to create db\n");
9270
9271     query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9272     res = MsiDatabaseOpenView( hdb, query, &htab );
9273     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9274     if(res == ERROR_SUCCESS )
9275     {
9276         res = MsiViewExecute( htab, hrec );
9277         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9278
9279         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9280         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9281
9282         size = sizeof(buffer);
9283         res = MsiRecordGetString(hrec, 1, buffer, &size );
9284         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9285         MsiCloseHandle( hrec );
9286
9287         res = MsiViewClose( htab );
9288         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9289
9290         res = MsiCloseHandle( htab );
9291         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9292     }
9293
9294     query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9295     res = MsiDatabaseOpenView( hdb, query, &htab );
9296     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9297     if(res == ERROR_SUCCESS )
9298     {
9299         res = MsiViewExecute( htab, 0 );
9300         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9301
9302         res = MsiViewClose( htab );
9303         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9304
9305         res = MsiCloseHandle( htab );
9306         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9307
9308         query = "SELECT * FROM `a`";
9309         res = MsiDatabaseOpenView( hdb, query, &htab );
9310         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9311
9312         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9313         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9314
9315         buffer[0] = 0;
9316         size = sizeof(buffer);
9317         res = MsiRecordGetString(hrec, 1, buffer, &size );
9318         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9319         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9320         MsiCloseHandle( hrec );
9321
9322         res = MsiViewClose( htab );
9323         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9324
9325         res = MsiCloseHandle( htab );
9326         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9327
9328         res = MsiDatabaseCommit(hdb);
9329         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9330
9331         res = MsiCloseHandle(hdb);
9332         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9333
9334         res = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
9335         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9336
9337         query = "SELECT * FROM `a`";
9338         res = MsiDatabaseOpenView( hdb, query, &htab );
9339         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9340
9341         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9342         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9343
9344         buffer[0] = 0;
9345         size = sizeof(buffer);
9346         res = MsiRecordGetString(hrec, 1, buffer, &size );
9347         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9348         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9349
9350         res = MsiCloseHandle( hrec );
9351         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9352
9353         res = MsiViewClose( htab );
9354         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9355
9356         res = MsiCloseHandle( htab );
9357         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9358     }
9359
9360     res = MsiDatabaseCommit(hdb);
9361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9362
9363     res = MsiCloseHandle(hdb);
9364     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9365
9366     DeleteFileA(msifile);
9367 }
9368
9369 static void test_embedded_nulls(void)
9370 {
9371     static const char control_table[] =
9372         "Dialog\tText\n"
9373         "s72\tL0\n"
9374         "Control\tDialog\n"
9375         "LicenseAgreementDlg\ttext\x11\x19text\0text";
9376     UINT r, sz;
9377     MSIHANDLE hdb, hrec;
9378     char buffer[32];
9379
9380     r = MsiOpenDatabaseA( msifile, MSIDBOPEN_CREATE, &hdb );
9381     ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
9382
9383     GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
9384     write_file( "temp_file", control_table, sizeof(control_table) );
9385     r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
9386     ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
9387     DeleteFileA( "temp_file" );
9388
9389     r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
9390     ok( r == ERROR_SUCCESS, "query failed %u\n", r );
9391
9392     buffer[0] = 0;
9393     sz = sizeof(buffer);
9394     r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
9395     ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
9396     ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
9397
9398     MsiCloseHandle( hrec );
9399     MsiCloseHandle( hdb );
9400     DeleteFileA( msifile );
9401 }
9402
9403 static void test_select_column_names(void)
9404 {
9405     MSIHANDLE hdb = 0, rec, rec2, view;
9406     char buffer[32];
9407     UINT r, size;
9408
9409     DeleteFile(msifile);
9410
9411     r = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
9412     ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r );
9413
9414     r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)");
9415     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9416
9417     r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" );
9418     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9419
9420     r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9421     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9422
9423     r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9424     todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
9425
9426     r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9427     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9428
9429     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" );
9430     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9431
9432     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" );
9433     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9434
9435     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" );
9436     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9437
9438     r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" );
9439     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9440
9441     r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" );
9442     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9443
9444     r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" );
9445     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9446
9447     r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" );
9448     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9449
9450     r = MsiDatabaseOpenView( hdb, "SELECT '' FROM `t`", &view );
9451     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9452
9453     r = MsiViewExecute( view, 0 );
9454     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9455
9456     r = MsiViewFetch( view, &rec );
9457     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9458     r = MsiRecordGetFieldCount( rec );
9459     ok( r == 1, "got %u\n",  r );
9460     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec2 );
9461     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9462     r = MsiRecordGetFieldCount( rec2 );
9463     ok( r == 1, "got %u\n",  r );
9464     size = sizeof(buffer);
9465     memset( buffer, 0x55, sizeof(buffer) );
9466     r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9467     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9468     ok( !buffer[0], "got \"%s\"\n", buffer );
9469     MsiCloseHandle( rec2 );
9470     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec2 );
9471     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9472     r = MsiRecordGetFieldCount( rec2 );
9473     ok( r == 1, "got %u\n",  r );
9474     size = sizeof(buffer);
9475     memset( buffer, 0x55, sizeof(buffer) );
9476     r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9477     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9478     ok( !lstrcmpA( buffer, "f0" ), "got \"%s\"\n", buffer );
9479     MsiCloseHandle( rec2 );
9480
9481     size = sizeof(buffer);
9482     memset( buffer, 0x55, sizeof(buffer) );
9483     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9484     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9485     ok( !buffer[0], "got \"%s\"\n", buffer );
9486     MsiCloseHandle( rec );
9487
9488     r = MsiViewFetch( view, &rec );
9489     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9490     size = sizeof(buffer);
9491     memset( buffer, 0x55, sizeof(buffer) );
9492     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9493     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9494     ok( !buffer[0], "got \"%s\"\n", buffer );
9495     MsiCloseHandle( rec );
9496
9497     r = MsiViewFetch( view, &rec );
9498     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9499     MsiCloseHandle( rec );
9500
9501     MsiViewClose( view );
9502     MsiCloseHandle( view );
9503
9504     r = MsiDatabaseOpenView( hdb, "SELECT `a`, '' FROM `t`", &view );
9505     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9506
9507     r = MsiViewExecute( view, 0 );
9508     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9509
9510     r = MsiViewFetch( view, &rec );
9511     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9512     r = MsiRecordGetFieldCount( rec );
9513     ok( r == 2, "got %u\n",  r );
9514     size = sizeof(buffer);
9515     memset( buffer, 0x55, sizeof(buffer) );
9516     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9517     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9518     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9519     MsiCloseHandle( rec );
9520
9521     r = MsiViewFetch( view, &rec );
9522     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9523     size = sizeof(buffer);
9524     memset( buffer, 0x55, sizeof(buffer) );
9525     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9526     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9527     ok( !buffer[0], "got \"%s\"\n", buffer );
9528     MsiCloseHandle( rec );
9529
9530     r = MsiViewFetch( view, &rec );
9531     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9532     MsiCloseHandle( rec );
9533
9534     MsiViewClose( view );
9535     MsiCloseHandle( view );
9536
9537     r = MsiDatabaseOpenView( hdb, "SELECT '', `a` FROM `t`", &view );
9538     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9539
9540     r = MsiViewExecute( view, 0 );
9541     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9542
9543     r = MsiViewFetch( view, &rec );
9544     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9545     r = MsiRecordGetFieldCount( rec );
9546     ok( r == 2, "got %u\n",  r );
9547     size = sizeof(buffer);
9548     memset( buffer, 0x55, sizeof(buffer) );
9549     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9550     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9551     ok( !buffer[0], "got \"%s\"\n", buffer );
9552     size = sizeof(buffer);
9553     memset( buffer, 0x55, sizeof(buffer) );
9554     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9555     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9556     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9557     MsiCloseHandle( rec );
9558
9559     r = MsiViewFetch( view, &rec );
9560     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9561     size = sizeof(buffer);
9562     memset( buffer, 0x55, sizeof(buffer) );
9563     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9564     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9565     ok( !buffer[0], "got \"%s\"\n", buffer );
9566     size = sizeof(buffer);
9567     memset( buffer, 0x55, sizeof(buffer) );
9568     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9569     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9570     ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9571     MsiCloseHandle( rec );
9572
9573     r = MsiViewFetch( view, &rec );
9574     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9575     MsiCloseHandle( rec );
9576
9577     MsiViewClose( view );
9578     MsiCloseHandle( view );
9579
9580     r = MsiDatabaseOpenView( hdb, "SELECT `a`, '', `b` FROM `t`", &view );
9581     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9582
9583     r = MsiViewExecute( view, 0 );
9584     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9585
9586     r = MsiViewFetch( view, &rec );
9587     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9588     r = MsiRecordGetFieldCount( rec );
9589     ok( r == 3, "got %u\n",  r );
9590     size = sizeof(buffer);
9591     memset( buffer, 0x55, sizeof(buffer) );
9592     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9593     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9594     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9595     size = sizeof(buffer);
9596     memset( buffer, 0x55, sizeof(buffer) );
9597     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9598     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9599     ok( !buffer[0], "got \"%s\"\n", buffer );
9600     size = sizeof(buffer);
9601     memset( buffer, 0x55, sizeof(buffer) );
9602     r = MsiRecordGetStringA( rec, 3, buffer, &size );
9603     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9604     ok( !lstrcmpA( buffer, "2" ), "got \"%s\"\n", buffer );
9605     MsiCloseHandle( rec );
9606
9607     r = MsiViewFetch( view, &rec );
9608     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9609     size = sizeof(buffer);
9610     memset( buffer, 0x55, sizeof(buffer) );
9611     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9612     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9613     ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9614     size = sizeof(buffer);
9615     memset( buffer, 0x55, sizeof(buffer) );
9616     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9617     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9618     ok( !buffer[0], "got \"%s\"\n", buffer );
9619     size = sizeof(buffer);
9620     memset( buffer, 0x55, sizeof(buffer) );
9621     r = MsiRecordGetStringA( rec, 3, buffer, &size );
9622     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9623     ok( !lstrcmpA( buffer, "4" ), "got \"%s\"\n", buffer );
9624     MsiCloseHandle( rec );
9625
9626     r = MsiViewFetch( view, &rec );
9627     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9628     MsiCloseHandle( rec );
9629
9630     MsiViewClose( view );
9631     MsiCloseHandle( view );
9632
9633     r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" );
9634     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9635
9636     r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" );
9637     todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9638
9639     r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" );
9640     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9641
9642     r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" );
9643     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9644
9645     r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" );
9646     todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9647
9648     r = MsiCloseHandle( hdb );
9649     ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r);
9650 }
9651
9652 START_TEST(db)
9653 {
9654     test_msidatabase();
9655     test_msiinsert();
9656     test_msidecomposedesc();
9657     test_msibadqueries();
9658     test_viewmodify();
9659     test_viewgetcolumninfo();
9660     test_getcolinfo();
9661     test_msiexport();
9662     test_longstrings();
9663     test_streamtable();
9664     test_binary();
9665     test_where_not_in_selected();
9666     test_where();
9667     test_msiimport();
9668     test_binary_import();
9669     test_markers();
9670     test_handle_limit();
9671     test_try_transform();
9672     test_join();
9673     test_temporary_table();
9674     test_alter();
9675     test_integers();
9676     test_update();
9677     test_special_tables();
9678     test_tables_order();
9679     test_rows_order();
9680     test_select_markers();
9681     test_viewmodify_update();
9682     test_viewmodify_assign();
9683     test_stringtable();
9684     test_viewmodify_delete();
9685     test_defaultdatabase();
9686     test_order();
9687     test_viewmodify_delete_temporary();
9688     test_deleterow();
9689     test_quotes();
9690     test_carriagereturn();
9691     test_noquotes();
9692     test_forcecodepage();
9693     test_viewmodify_refresh();
9694     test_where_viewmodify();
9695     test_storages_table();
9696     test_dbtopackage();
9697     test_droptable();
9698     test_dbmerge();
9699     test_select_with_tablenames();
9700     test_insertorder();
9701     test_columnorder();
9702     test_suminfo_import();
9703     test_createtable();
9704     test_collation();
9705     test_embedded_nulls();
9706     test_select_column_names();
9707 }