Release 1.4.1.
[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     r = MsiCloseHandle(hrec);
927     ok(r == ERROR_SUCCESS, "failed to close record\n");
928
929     r = MsiViewClose(hview);
930     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
931     r = MsiCloseHandle(hview);
932     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
933
934     query = "SELECT * FROM `phone`";
935     r = MsiDatabaseOpenView(hdb, query, &hview);
936     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
937
938     r = MsiViewExecute(hview, 0);
939     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
940
941     r = MsiViewFetch(hview, &hrec);
942     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
943
944     r = MsiRecordGetInteger(hrec, 1);
945     ok(r == 1, "Expected 1, got %d\n", r);
946
947     sz = sizeof(buffer);
948     r = MsiRecordGetString(hrec, 2, buffer, &sz);
949     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
950     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
951
952     sz = sizeof(buffer);
953     r = MsiRecordGetString(hrec, 3, buffer, &sz);
954     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
955     ok(!lstrcmp(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
956
957     /* update the view, non-primary key */
958     r = MsiRecordSetString(hrec, 3, "3141592");
959     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
960
961     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
962     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
963
964     /* do it again */
965     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
966     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
967
968     /* update the view, primary key */
969     r = MsiRecordSetInteger(hrec, 1, 5);
970     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
971
972     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
973     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
974
975     r = MsiCloseHandle(hrec);
976     ok(r == ERROR_SUCCESS, "failed to close record\n");
977
978     r = MsiViewClose(hview);
979     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
980     r = MsiCloseHandle(hview);
981     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
982
983     query = "SELECT * FROM `phone`";
984     r = MsiDatabaseOpenView(hdb, query, &hview);
985     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
986
987     r = MsiViewExecute(hview, 0);
988     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
989
990     r = MsiViewFetch(hview, &hrec);
991     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
992
993     r = MsiRecordGetInteger(hrec, 1);
994     ok(r == 1, "Expected 1, got %d\n", r);
995
996     sz = sizeof(buffer);
997     r = MsiRecordGetString(hrec, 2, buffer, &sz);
998     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
999     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
1000
1001     sz = sizeof(buffer);
1002     r = MsiRecordGetString(hrec, 3, buffer, &sz);
1003     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1004     ok(!lstrcmp(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
1005
1006     r = MsiCloseHandle(hrec);
1007     ok(r == ERROR_SUCCESS, "failed to close record\n");
1008
1009     /* use a record that doesn't come from a view fetch */
1010     hrec = MsiCreateRecord(3);
1011     ok(hrec != 0, "MsiCreateRecord failed\n");
1012
1013     r = MsiRecordSetInteger(hrec, 1, 3);
1014     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1015     r = MsiRecordSetString(hrec, 2, "jane");
1016     ok(r == ERROR_SUCCESS, "failed to set string\n");
1017     r = MsiRecordSetString(hrec, 3, "112358");
1018     ok(r == ERROR_SUCCESS, "failed to set string\n");
1019
1020     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1021     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
1022
1023     r = MsiCloseHandle(hrec);
1024     ok(r == ERROR_SUCCESS, "failed to close record\n");
1025
1026     /* use a record that doesn't come from a view fetch, primary key matches */
1027     hrec = MsiCreateRecord(3);
1028     ok(hrec != 0, "MsiCreateRecord failed\n");
1029
1030     r = MsiRecordSetInteger(hrec, 1, 1);
1031     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1032     r = MsiRecordSetString(hrec, 2, "jane");
1033     ok(r == ERROR_SUCCESS, "failed to set string\n");
1034     r = MsiRecordSetString(hrec, 3, "112358");
1035     ok(r == ERROR_SUCCESS, "failed to set string\n");
1036
1037     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1038     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1039
1040     r = MsiCloseHandle(hrec);
1041     ok(r == ERROR_SUCCESS, "failed to close record\n");
1042
1043     hrec = MsiCreateRecord(3);
1044
1045     r = MsiRecordSetInteger(hrec, 1, 2);
1046     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1047     r = MsiRecordSetString(hrec, 2, "nick");
1048     ok(r == ERROR_SUCCESS, "failed to set string\n");
1049     r = MsiRecordSetString(hrec, 3, "141421");
1050     ok(r == ERROR_SUCCESS, "failed to set string\n");
1051
1052     r = MsiViewExecute(hview, 0);
1053     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1054     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
1055     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1056
1057     r = MsiCloseHandle(hrec);
1058     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1059     r = MsiViewClose(hview);
1060     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1061     r = MsiCloseHandle(hview);
1062     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1063
1064     query = "SELECT * FROM `phone` WHERE `id` = 1";
1065     r = MsiDatabaseOpenView(hdb, query, &hview);
1066     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1067     r = MsiViewExecute(hview, 0);
1068     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1069     r = MsiViewFetch(hview, &hrec);
1070     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1071
1072     /* change the id to match the second row */
1073     r = MsiRecordSetInteger(hrec, 1, 2);
1074     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1075     r = MsiRecordSetString(hrec, 2, "jerry");
1076     ok(r == ERROR_SUCCESS, "failed to set string\n");
1077
1078     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1079     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1080
1081     r = MsiCloseHandle(hrec);
1082     ok(r == ERROR_SUCCESS, "failed to close record\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     /* broader search */
1089     query = "SELECT * FROM `phone` ORDER BY `id`";
1090     r = MsiDatabaseOpenView(hdb, query, &hview);
1091     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1092     r = MsiViewExecute(hview, 0);
1093     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1094     r = MsiViewFetch(hview, &hrec);
1095     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1096
1097     /* change the id to match the second row */
1098     r = MsiRecordSetInteger(hrec, 1, 2);
1099     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1100     r = MsiRecordSetString(hrec, 2, "jerry");
1101     ok(r == ERROR_SUCCESS, "failed to set string\n");
1102
1103     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1104     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1105
1106     r = MsiCloseHandle(hrec);
1107     ok(r == ERROR_SUCCESS, "failed to close record\n");
1108     r = MsiViewClose(hview);
1109     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1110     r = MsiCloseHandle(hview);
1111     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1112
1113     r = MsiCloseHandle( hdb );
1114     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1115 }
1116
1117 static MSIHANDLE create_db(void)
1118 {
1119     MSIHANDLE hdb = 0;
1120     UINT res;
1121
1122     DeleteFile(msifile);
1123
1124     /* create an empty database */
1125     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1126     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1127     if( res != ERROR_SUCCESS )
1128         return hdb;
1129
1130     res = MsiDatabaseCommit( hdb );
1131     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1132
1133     return hdb;
1134 }
1135
1136 static void test_getcolinfo(void)
1137 {
1138     MSIHANDLE hdb, hview = 0, rec = 0;
1139     UINT r;
1140     DWORD sz;
1141     char buffer[0x20];
1142
1143     /* create an empty db */
1144     hdb = create_db();
1145     ok( hdb, "failed to create db\n");
1146
1147     /* tables should be present */
1148     r = MsiDatabaseOpenView(hdb, "select * from _Tables", &hview);
1149     ok( r == ERROR_SUCCESS, "failed to open query\n");
1150
1151     r = MsiViewExecute(hview, 0);
1152     ok( r == ERROR_SUCCESS, "failed to execute query\n");
1153
1154     /* check that NAMES works */
1155     rec = 0;
1156     r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1157     ok( r == ERROR_SUCCESS, "failed to get names\n");
1158     sz = sizeof buffer;
1159     r = MsiRecordGetString(rec, 1, buffer, &sz );
1160     ok( r == ERROR_SUCCESS, "failed to get string\n");
1161     ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
1162     r = MsiCloseHandle( rec );
1163     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1164
1165     /* check that TYPES works */
1166     rec = 0;
1167     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1168     ok( r == ERROR_SUCCESS, "failed to get names\n");
1169     sz = sizeof buffer;
1170     r = MsiRecordGetString(rec, 1, buffer, &sz );
1171     ok( r == ERROR_SUCCESS, "failed to get string\n");
1172     ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
1173     r = MsiCloseHandle( rec );
1174     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1175
1176     /* check that invalid values fail */
1177     rec = 0;
1178     r = MsiViewGetColumnInfo( hview, 100, &rec );
1179     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1180     ok( rec == 0, "returned a record\n");
1181
1182     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1183     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1184
1185     r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1186     ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1187
1188     r = MsiViewClose(hview);
1189     ok( r == ERROR_SUCCESS, "failed to close view\n");
1190     r = MsiCloseHandle(hview);
1191     ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1192     r = MsiCloseHandle(hdb);
1193     ok( r == ERROR_SUCCESS, "failed to close database\n");
1194 }
1195
1196 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1197 {
1198     MSIHANDLE hview = 0, rec = 0;
1199     UINT r;
1200
1201     r = MsiDatabaseOpenView(hdb, query, &hview);
1202     if( r != ERROR_SUCCESS )
1203         return r;
1204
1205     r = MsiViewExecute(hview, 0);
1206     if( r == ERROR_SUCCESS )
1207     {
1208         MsiViewGetColumnInfo( hview, type, &rec );
1209     }
1210     MsiViewClose(hview);
1211     MsiCloseHandle(hview);
1212     return rec;
1213 }
1214
1215 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1216 {
1217     MSIHANDLE hview = 0, rec = 0;
1218     UINT r, type = 0;
1219     char query[0x100];
1220
1221     sprintf(query, "select * from `_Columns` where  `Table` = '%s'", table );
1222
1223     r = MsiDatabaseOpenView(hdb, query, &hview);
1224     if( r != ERROR_SUCCESS )
1225         return r;
1226
1227     r = MsiViewExecute(hview, 0);
1228     if( r == ERROR_SUCCESS )
1229     {
1230         while (1)
1231         {
1232             r = MsiViewFetch( hview, &rec );
1233             if( r != ERROR_SUCCESS)
1234                 break;
1235             r = MsiRecordGetInteger( rec, 2 );
1236             if (r == field)
1237                 type = MsiRecordGetInteger( rec, 4 );
1238             MsiCloseHandle( rec );
1239         }
1240     }
1241     MsiViewClose(hview);
1242     MsiCloseHandle(hview);
1243     return type;
1244 }
1245
1246 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
1247 {
1248     CHAR buffer[0x20];
1249     UINT r;
1250     DWORD sz;
1251
1252     sz = sizeof buffer;
1253     r = MsiRecordGetString( rec, field, buffer, &sz );
1254     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1255 }
1256
1257 static void test_viewgetcolumninfo(void)
1258 {
1259     MSIHANDLE hdb = 0, rec;
1260     UINT r;
1261
1262     hdb = create_db();
1263     ok( hdb, "failed to create db\n");
1264
1265     r = run_query( hdb, 0,
1266             "CREATE TABLE `Properties` "
1267             "( `Property` CHAR(255), "
1268             "  `Value` CHAR(1), "
1269             "  `Intvalue` INT, "
1270             "  `Integervalue` INTEGER, "
1271             "  `Shortvalue` SHORT, "
1272             "  `Longvalue` LONG, "
1273             "  `Longcharvalue` LONGCHAR "
1274             "  PRIMARY KEY `Property`)" );
1275     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1276
1277     /* check the column types */
1278     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1279     ok( rec, "failed to get column info record\n" );
1280
1281     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1282     ok( check_record( rec, 2, "S1"), "wrong record type\n");
1283     ok( check_record( rec, 3, "I2"), "wrong record type\n");
1284     ok( check_record( rec, 4, "I2"), "wrong record type\n");
1285     ok( check_record( rec, 5, "I2"), "wrong record type\n");
1286     ok( check_record( rec, 6, "I4"), "wrong record type\n");
1287     ok( check_record( rec, 7, "S0"), "wrong record type\n");
1288
1289     MsiCloseHandle( rec );
1290
1291     /* check the type in _Columns */
1292     ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1293     ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1294     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1295     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1296     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1297     ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1298     ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1299
1300     /* now try the names */
1301     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1302     ok( rec, "failed to get column info record\n" );
1303
1304     ok( check_record( rec, 1, "Property"), "wrong record type\n");
1305     ok( check_record( rec, 2, "Value"), "wrong record type\n");
1306     ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
1307     ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
1308     ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
1309     ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
1310     ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
1311
1312     MsiCloseHandle( rec );
1313
1314     r = run_query( hdb, 0,
1315             "CREATE TABLE `Binary` "
1316             "( `Name` CHAR(255), `Data` OBJECT  PRIMARY KEY `Name`)" );
1317     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1318
1319     /* check the column types */
1320     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1321     ok( rec, "failed to get column info record\n" );
1322
1323     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1324     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1325
1326     MsiCloseHandle( rec );
1327
1328     /* check the type in _Columns */
1329     ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1330     ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1331
1332     /* now try the names */
1333     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1334     ok( rec, "failed to get column info record\n" );
1335
1336     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1337     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1338     MsiCloseHandle( rec );
1339
1340     r = run_query( hdb, 0,
1341             "CREATE TABLE `UIText` "
1342             "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1343     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1344
1345     ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1346     ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1347
1348     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1349     ok( rec, "failed to get column info record\n" );
1350     ok( check_record( rec, 1, "Key"), "wrong record type\n");
1351     ok( check_record( rec, 2, "Text"), "wrong record type\n");
1352     MsiCloseHandle( rec );
1353
1354     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1355     ok( rec, "failed to get column info record\n" );
1356     ok( check_record( rec, 1, "s72"), "wrong record type\n");
1357     ok( check_record( rec, 2, "L255"), "wrong record type\n");
1358     MsiCloseHandle( rec );
1359
1360     MsiCloseHandle( hdb );
1361 }
1362
1363 static void test_msiexport(void)
1364 {
1365     MSIHANDLE hdb = 0, hview = 0;
1366     UINT r;
1367     const char *query;
1368     char path[MAX_PATH];
1369     const char file[] = "phone.txt";
1370     HANDLE handle;
1371     char buffer[0x100];
1372     DWORD length;
1373     const char expected[] =
1374         "id\tname\tnumber\r\n"
1375         "I2\tS32\tS32\r\n"
1376         "phone\tid\r\n"
1377         "1\tAbe\t8675309\r\n";
1378
1379     DeleteFile(msifile);
1380
1381     /* just MsiOpenDatabase should not create a file */
1382     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1383     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1384
1385     /* create a table */
1386     query = "CREATE TABLE `phone` ( "
1387             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1388             "PRIMARY KEY `id`)";
1389     r = MsiDatabaseOpenView(hdb, query, &hview);
1390     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1391     r = MsiViewExecute(hview, 0);
1392     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1393     r = MsiViewClose(hview);
1394     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1395     r = MsiCloseHandle(hview);
1396     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1397
1398     /* insert a value into it */
1399     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1400         "VALUES('1', 'Abe', '8675309')";
1401     r = MsiDatabaseOpenView(hdb, query, &hview);
1402     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1403     r = MsiViewExecute(hview, 0);
1404     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1405     r = MsiViewClose(hview);
1406     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1407     r = MsiCloseHandle(hview);
1408     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1409
1410     GetCurrentDirectory(MAX_PATH, path);
1411
1412     r = MsiDatabaseExport(hdb, "phone", path, file);
1413     ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1414
1415     MsiCloseHandle(hdb);
1416
1417     lstrcat(path, "\\");
1418     lstrcat(path, file);
1419
1420     /* check the data that was written */
1421     length = 0;
1422     memset(buffer, 0, sizeof buffer);
1423     handle = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1424     if (handle != INVALID_HANDLE_VALUE)
1425     {
1426         ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1427         CloseHandle(handle);
1428         DeleteFile(path);
1429     }
1430     else
1431         ok(0, "failed to open file %s\n", path);
1432
1433     ok( length == strlen(expected), "length of data wrong\n");
1434     ok( !lstrcmp(buffer, expected), "data doesn't match\n");
1435     DeleteFile(msifile);
1436 }
1437
1438 static void test_longstrings(void)
1439 {
1440     const char insert_query[] = 
1441         "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1442     char *str;
1443     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1444     DWORD len;
1445     UINT r;
1446     const DWORD STRING_LENGTH = 0x10005;
1447
1448     DeleteFile(msifile);
1449     /* just MsiOpenDatabase should not create a file */
1450     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1451     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1452
1453     /* create a table */
1454     r = try_query( hdb, 
1455         "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1456     ok(r == ERROR_SUCCESS, "query failed\n");
1457
1458     /* try a insert a very long string */
1459     str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
1460     len = strchr(insert_query, 'Z') - insert_query;
1461     strcpy(str, insert_query);
1462     memset(str+len, 'Z', STRING_LENGTH);
1463     strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1464     r = try_query( hdb, str );
1465     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1466
1467     HeapFree(GetProcessHeap(), 0, str);
1468
1469     MsiDatabaseCommit(hdb);
1470     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1471     MsiCloseHandle(hdb);
1472
1473     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
1474     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1475
1476     r = MsiDatabaseOpenView(hdb, "select * from `strings` where `id` = 1", &hview);
1477     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1478
1479     r = MsiViewExecute(hview, 0);
1480     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1481
1482     r = MsiViewFetch(hview, &hrec);
1483     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1484
1485     MsiViewClose(hview);
1486     MsiCloseHandle(hview);
1487
1488     r = MsiRecordGetString(hrec, 2, NULL, &len);
1489     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1490     ok(len == STRING_LENGTH, "string length wrong\n");
1491
1492     MsiCloseHandle(hrec);
1493     MsiCloseHandle(hdb);
1494     DeleteFile(msifile);
1495 }
1496
1497 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1498 {
1499     HANDLE file;
1500     DWORD written;
1501
1502     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1503     if (file == INVALID_HANDLE_VALUE)
1504         return;
1505
1506     WriteFile(file, data, strlen(data), &written, NULL);
1507     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1508
1509     if (size)
1510     {
1511         SetFilePointer(file, size, NULL, FILE_BEGIN);
1512         SetEndOfFile(file);
1513     }
1514
1515     CloseHandle(file);
1516 }
1517
1518 #define create_file(name) create_file_data(name, name, 0)
1519  
1520 static void test_streamtable(void)
1521 {
1522     MSIHANDLE hdb = 0, rec, view, hsi;
1523     char file[MAX_PATH];
1524     char buf[MAX_PATH];
1525     DWORD size;
1526     UINT r;
1527
1528     hdb = create_db();
1529     ok( hdb, "failed to create db\n");
1530
1531     r = run_query( hdb, 0,
1532             "CREATE TABLE `Properties` "
1533             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
1534     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1535
1536     r = run_query( hdb, 0,
1537             "INSERT INTO `Properties` "
1538             "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1539     ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1540
1541     r = MsiDatabaseCommit( hdb );
1542     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1543
1544     MsiCloseHandle( hdb );
1545
1546     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
1547     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1548
1549     /* check the column types */
1550     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1551     ok( rec, "failed to get column info record\n" );
1552
1553     ok( check_record( rec, 1, "s62"), "wrong record type\n");
1554     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1555
1556     MsiCloseHandle( rec );
1557
1558     /* now try the names */
1559     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1560     ok( rec, "failed to get column info record\n" );
1561
1562     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1563     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1564
1565     MsiCloseHandle( rec );
1566
1567     r = MsiDatabaseOpenView( hdb,
1568             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1569     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1570
1571     r = MsiViewExecute( view, 0 );
1572     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1573
1574     r = MsiViewFetch( view, &rec );
1575     ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1576
1577     MsiCloseHandle( rec );
1578     MsiViewClose( view );
1579     MsiCloseHandle( view );
1580
1581     /* create a summary information stream */
1582     r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1583     ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1584
1585     r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1586     ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1587
1588     r = MsiSummaryInfoPersist( hsi );
1589     ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1590
1591     MsiCloseHandle( hsi );
1592
1593     r = MsiDatabaseOpenView( hdb,
1594             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1595     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1596
1597     r = MsiViewExecute( view, 0 );
1598     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1599
1600     r = MsiViewFetch( view, &rec );
1601     ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1602
1603     MsiCloseHandle( rec );
1604     MsiViewClose( view );
1605     MsiCloseHandle( view );
1606
1607     /* insert a file into the _Streams table */
1608     create_file( "test.txt" );
1609
1610     rec = MsiCreateRecord( 2 );
1611     MsiRecordSetString( rec, 1, "data" );
1612
1613     r = MsiRecordSetStream( rec, 2, "test.txt" );
1614     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1615
1616     DeleteFile("test.txt");
1617
1618     r = MsiDatabaseOpenView( hdb,
1619             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1620     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1621
1622     r = MsiViewExecute( view, rec );
1623     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1624
1625     MsiCloseHandle( rec );
1626     MsiViewClose( view );
1627     MsiCloseHandle( view );
1628
1629     /* insert another one */
1630     create_file( "test1.txt" );
1631
1632     rec = MsiCreateRecord( 2 );
1633     MsiRecordSetString( rec, 1, "data1" );
1634
1635     r = MsiRecordSetStream( rec, 2, "test1.txt" );
1636     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1637
1638     DeleteFile("test1.txt");
1639
1640     r = MsiDatabaseOpenView( hdb,
1641             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1642     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1643
1644     r = MsiViewExecute( view, rec );
1645     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1646
1647     MsiCloseHandle( rec );
1648     MsiViewClose( view );
1649     MsiCloseHandle( view );
1650
1651     r = MsiDatabaseOpenView( hdb,
1652             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1653     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1654
1655     r = MsiViewExecute( view, 0 );
1656     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1657
1658     r = MsiViewFetch( view, &rec );
1659     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1660
1661     size = MAX_PATH;
1662     r = MsiRecordGetString( rec, 1, file, &size );
1663     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1664     ok( !lstrcmp(file, "data"), "Expected 'data', got %s\n", file);
1665
1666     size = MAX_PATH;
1667     memset(buf, 0, MAX_PATH);
1668     r = MsiRecordReadStream( rec, 2, buf, &size );
1669     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1670     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf);
1671
1672     MsiCloseHandle( rec );
1673     MsiViewClose( view );
1674     MsiCloseHandle( view );
1675
1676     r = MsiDatabaseOpenView( hdb,
1677             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1678     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1679
1680     r = MsiViewExecute( view, 0 );
1681     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1682
1683     r = MsiViewFetch( view, &rec );
1684     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1685
1686     size = MAX_PATH;
1687     r = MsiRecordGetString( rec, 1, file, &size );
1688     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1689     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1690
1691     size = MAX_PATH;
1692     memset(buf, 0, MAX_PATH);
1693     r = MsiRecordReadStream( rec, 2, buf, &size );
1694     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1695     ok( !lstrcmp(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
1696
1697     MsiCloseHandle( rec );
1698     MsiViewClose( view );
1699     MsiCloseHandle( view );
1700
1701     /* perform an update */
1702     create_file( "test2.txt" );
1703     rec = MsiCreateRecord( 1 );
1704
1705     r = MsiRecordSetStream( rec, 1, "test2.txt" );
1706     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1707
1708     DeleteFile("test2.txt");
1709
1710     r = MsiDatabaseOpenView( hdb,
1711             "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1712     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1713
1714     r = MsiViewExecute( view, rec );
1715     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1716
1717     MsiCloseHandle( rec );
1718     MsiViewClose( view );
1719     MsiCloseHandle( view );
1720
1721     r = MsiDatabaseOpenView( hdb,
1722             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1723     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1724
1725     r = MsiViewExecute( view, 0 );
1726     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1727
1728     r = MsiViewFetch( view, &rec );
1729     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1730
1731     size = MAX_PATH;
1732     r = MsiRecordGetString( rec, 1, file, &size );
1733     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1734     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1735
1736     size = MAX_PATH;
1737     memset(buf, 0, MAX_PATH);
1738     r = MsiRecordReadStream( rec, 2, buf, &size );
1739     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1740     todo_wine ok( !lstrcmp(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
1741
1742     MsiCloseHandle( rec );
1743     MsiViewClose( view );
1744     MsiCloseHandle( view );
1745     MsiCloseHandle( hdb );
1746     DeleteFile(msifile);
1747 }
1748
1749 static void test_binary(void)
1750 {
1751     MSIHANDLE hdb = 0, rec;
1752     char file[MAX_PATH];
1753     char buf[MAX_PATH];
1754     DWORD size;
1755     LPCSTR query;
1756     UINT r;
1757
1758     /* insert a file into the Binary table */
1759     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1760     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1761
1762     query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
1763     r = run_query( hdb, 0, query );
1764     ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1765
1766     create_file( "test.txt" );
1767     rec = MsiCreateRecord( 1 );
1768     r = MsiRecordSetStream( rec, 1, "test.txt" );
1769     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1770     DeleteFile( "test.txt" );
1771
1772     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1773     r = run_query( hdb, rec, query );
1774     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1775
1776     r = MsiCloseHandle( rec );
1777     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1778
1779     r = MsiDatabaseCommit( hdb );
1780     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1781
1782     r = MsiCloseHandle( hdb );
1783     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1784
1785     /* read file from the Stream table */
1786     r = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
1787     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1788
1789     query = "SELECT * FROM `_Streams`";
1790     r = do_query( hdb, query, &rec );
1791     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1792
1793     size = MAX_PATH;
1794     r = MsiRecordGetString( rec, 1, file, &size );
1795     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1796     ok( !lstrcmp(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1797
1798     size = MAX_PATH;
1799     memset( buf, 0, MAX_PATH );
1800     r = MsiRecordReadStream( rec, 2, buf, &size );
1801     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1802     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1803
1804     r = MsiCloseHandle( rec );
1805     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1806
1807     /* read file from the Binary table */
1808     query = "SELECT * FROM `Binary`";
1809     r = do_query( hdb, query, &rec );
1810     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1811
1812     size = MAX_PATH;
1813     r = MsiRecordGetString( rec, 1, file, &size );
1814     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1815     ok( !lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file );
1816
1817     size = MAX_PATH;
1818     memset( buf, 0, MAX_PATH );
1819     r = MsiRecordReadStream( rec, 3, buf, &size );
1820     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1821     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1822
1823     r = MsiCloseHandle( rec );
1824     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1825
1826     r = MsiCloseHandle( hdb );
1827     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1828
1829     DeleteFile( msifile );
1830 }
1831
1832 static void test_where_not_in_selected(void)
1833 {
1834     MSIHANDLE hdb = 0, rec, view;
1835     LPCSTR query;
1836     UINT r;
1837
1838     hdb = create_db();
1839     ok( hdb, "failed to create db\n");
1840
1841     r = run_query(hdb, 0,
1842             "CREATE TABLE `IESTable` ("
1843             "`Action` CHAR(64), "
1844             "`Condition` CHAR(64), "
1845             "`Sequence` LONG PRIMARY KEY `Sequence`)");
1846     ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1847
1848     r = run_query(hdb, 0,
1849             "CREATE TABLE `CATable` ("
1850             "`Action` CHAR(64), "
1851             "`Type` LONG PRIMARY KEY `Type`)");
1852     ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1853
1854     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1855             "( `Action`, `Condition`, `Sequence`) "
1856             "VALUES ( 'clean', 'cond4', 4)");
1857     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1858
1859     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1860             "( `Action`, `Condition`, `Sequence`) "
1861             "VALUES ( 'depends', 'cond1', 1)");
1862     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1863
1864     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1865             "( `Action`, `Condition`, `Sequence`) "
1866             "VALUES ( 'build', 'cond2', 2)");
1867     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1868
1869     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1870             "( `Action`, `Condition`, `Sequence`) "
1871             "VALUES ( 'build2', 'cond6', 6)");
1872     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1873
1874     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1875             "( `Action`, `Condition`, `Sequence`) "
1876             "VALUES ( 'build', 'cond3', 3)");
1877     ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1878
1879     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1880             "( `Action`, `Type` ) "
1881             "VALUES ( 'build', 32)");
1882     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1883
1884     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1885             "( `Action`, `Type` ) "
1886             "VALUES ( 'depends', 64)");
1887     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1888
1889     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1890             "( `Action`, `Type` ) "
1891             "VALUES ( 'clean', 63)");
1892     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1893
1894     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1895             "( `Action`, `Type` ) "
1896             "VALUES ( 'build2', 34)");
1897     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1898     query = "Select IESTable.Condition from CATable, IESTable where "
1899             "CATable.Action = IESTable.Action and CATable.Type = 32";
1900     r = MsiDatabaseOpenView(hdb, query, &view);
1901     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1902
1903     r = MsiViewExecute(view, 0);
1904     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1905
1906     r = MsiViewFetch(view, &rec);
1907     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1908
1909     ok( check_record( rec, 1, "cond2"), "wrong condition\n");
1910
1911     MsiCloseHandle( rec );
1912     r = MsiViewFetch(view, &rec);
1913     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1914
1915     ok( check_record( rec, 1, "cond3"), "wrong condition\n");
1916
1917     MsiCloseHandle( rec );
1918     MsiViewClose(view);
1919     MsiCloseHandle(view);
1920
1921     MsiCloseHandle( hdb );
1922     DeleteFile(msifile);
1923
1924 }
1925
1926
1927 static void test_where(void)
1928 {
1929     MSIHANDLE hdb = 0, rec, view;
1930     LPCSTR query;
1931     UINT r;
1932     DWORD size;
1933     CHAR buf[MAX_PATH];
1934     UINT count;
1935
1936     hdb = create_db();
1937     ok( hdb, "failed to create db\n");
1938
1939     r = run_query( hdb, 0,
1940             "CREATE TABLE `Media` ("
1941             "`DiskId` SHORT NOT NULL, "
1942             "`LastSequence` LONG, "
1943             "`DiskPrompt` CHAR(64) LOCALIZABLE, "
1944             "`Cabinet` CHAR(255), "
1945             "`VolumeLabel` CHAR(32), "
1946             "`Source` CHAR(72) "
1947             "PRIMARY KEY `DiskId`)" );
1948     ok( r == S_OK, "cannot create Media table: %d\n", r );
1949
1950     r = run_query( hdb, 0, "INSERT INTO `Media` "
1951             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1952             "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
1953     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1954
1955     r = run_query( hdb, 0, "INSERT INTO `Media` "
1956             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1957             "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
1958     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1959
1960     r = run_query( hdb, 0, "INSERT INTO `Media` "
1961             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1962             "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
1963     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1964
1965     query = "SELECT * FROM `Media`";
1966     r = do_query(hdb, query, &rec);
1967     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1968     ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
1969     MsiCloseHandle( rec );
1970
1971     query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
1972     r = do_query(hdb, query, &rec);
1973     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1974     ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
1975
1976     r = MsiRecordGetInteger(rec, 1);
1977     ok( 2 == r, "field wrong\n");
1978     r = MsiRecordGetInteger(rec, 2);
1979     ok( 1 == r, "field wrong\n");
1980     MsiCloseHandle( rec );
1981
1982     query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
1983     r = MsiDatabaseOpenView(hdb, query, &view);
1984     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1985
1986     r = MsiViewExecute(view, 0);
1987     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1988
1989     r = MsiViewFetch(view, &rec);
1990     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1991
1992     count = MsiRecordGetFieldCount( rec );
1993     ok( count == 1, "Expected 1 record fields, got %d\n", count );
1994
1995     size = MAX_PATH;
1996     r = MsiRecordGetString( rec, 1, buf, &size );
1997     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
1998     ok( !lstrcmp( buf, "2" ),
1999         "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
2000     MsiCloseHandle( rec );
2001
2002     r = MsiViewFetch(view, &rec);
2003     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2004
2005     size = MAX_PATH;
2006     r = MsiRecordGetString( rec, 1, buf, &size );
2007     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2008     ok( !lstrcmp( buf, "3" ),
2009         "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
2010     MsiCloseHandle( rec );
2011
2012     r = MsiViewFetch(view, &rec);
2013     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
2014
2015     MsiViewClose(view);
2016     MsiCloseHandle(view);
2017
2018     MsiCloseHandle( rec );
2019
2020     rec = 0;
2021     query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
2022     r = do_query(hdb, query, &rec);
2023     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2024     MsiCloseHandle( rec );
2025
2026     rec = 0;
2027     query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
2028     r = do_query(hdb, query, &rec);
2029     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2030     MsiCloseHandle( rec );
2031
2032     rec = 0;
2033     query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
2034     r = do_query(hdb, query, &rec);
2035     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2036     MsiCloseHandle( rec );
2037
2038     rec = 0;
2039     query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
2040     r = do_query(hdb, query, &rec);
2041     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2042     MsiCloseHandle( rec );
2043
2044     rec = 0;
2045     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
2046     r = do_query(hdb, query, &rec);
2047     ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
2048     MsiCloseHandle( rec );
2049
2050     rec = MsiCreateRecord(1);
2051     MsiRecordSetString(rec, 1, "");
2052
2053     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
2054     r = MsiDatabaseOpenView(hdb, query, &view);
2055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2056     r = MsiViewExecute(view, rec);
2057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2058
2059     MsiCloseHandle(rec);
2060
2061     r = MsiViewFetch(view, &rec);
2062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2063
2064     MsiCloseHandle(rec);
2065     MsiViewClose(view);
2066     MsiCloseHandle(view);
2067
2068     MsiCloseHandle( hdb );
2069     DeleteFile(msifile);
2070 }
2071
2072 static CHAR CURR_DIR[MAX_PATH];
2073
2074 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
2075                                 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
2076                                 "TestTable\tFirstPrimaryColumn\n"
2077                                 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
2078
2079 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
2080                                   "s255\ts255\n"
2081                                   "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
2082                                   "papaya\tleaf\n"
2083                                   "papaya\tflower\n";
2084
2085 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
2086                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2087                                 "Table\tA\r\n"
2088                                 "a\tb\tc\td\te\tf\n"
2089                                 "g\th\ti\t\rj\tk\tl\r\n";
2090
2091 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
2092                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2093                                 "Table2\tA\r\n"
2094                                 "a\tb\tc\td\te\tf\n"
2095                                 "g\th\ti\tj\tk\tl\r\n";
2096
2097 static const CHAR suminfo[] = "PropertyId\tValue\n"
2098                               "i2\tl255\n"
2099                               "_SummaryInformation\tPropertyId\n"
2100                               "1\t1252\n"
2101                               "2\tInstaller Database\n"
2102                               "3\tInstaller description\n"
2103                               "4\tWineHQ\n"
2104                               "5\tInstaller\n"
2105                               "6\tInstaller comments\n"
2106                               "7\tIntel;1033,2057\n"
2107                               "9\t{12345678-1234-1234-1234-123456789012}\n"
2108                               "12\t2009/04/12 15:46:11\n"
2109                               "13\t2009/04/12 15:46:11\n"
2110                               "14\t200\n"
2111                               "15\t2\n"
2112                               "18\tVim\n"
2113                               "19\t2\n";
2114
2115 static void write_file(const CHAR *filename, const char *data, int data_size)
2116 {
2117     DWORD size;
2118
2119     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
2120                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2121
2122     WriteFile(hf, data, data_size, &size, NULL);
2123     CloseHandle(hf);
2124 }
2125
2126 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2127 {
2128     UINT r;
2129
2130     write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
2131     r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2132     DeleteFileA("temp_file");
2133
2134     return r;
2135 }
2136
2137 static void test_suminfo_import(void)
2138 {
2139     MSIHANDLE hdb, hsi, view = 0;
2140     LPCSTR query;
2141     UINT r, count, size, type;
2142     char str_value[50];
2143     INT int_value;
2144     FILETIME ft_value;
2145
2146     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2147
2148     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2150
2151     r = add_table_to_db(hdb, suminfo);
2152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2153
2154     /* _SummaryInformation is not imported as a regular table... */
2155
2156     query = "SELECT * FROM `_SummaryInformation`";
2157     r = MsiDatabaseOpenViewA(hdb, query, &view);
2158     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2159     MsiCloseHandle(view);
2160
2161     /* ...its data is added to the special summary information stream */
2162
2163     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2165
2166     r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2168     ok(count == 14, "Expected 14, got %u\n", count);
2169
2170     r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2172     ok(type ==  VT_I2, "Expected VT_I2, got %u\n", type);
2173     ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2174
2175     size = sizeof(str_value);
2176     r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2178     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2179     ok(size == 18, "Expected 18, got %u\n", size);
2180     ok(!strcmp(str_value, "Installer Database"),
2181        "Expected \"Installer Database\", got %s\n", str_value);
2182
2183     size = sizeof(str_value);
2184     r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2186     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2187     ok(!strcmp(str_value, "Installer description"),
2188        "Expected \"Installer description\", got %s\n", str_value);
2189
2190     size = sizeof(str_value);
2191     r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2193     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2194     ok(!strcmp(str_value, "WineHQ"),
2195        "Expected \"WineHQ\", got %s\n", str_value);
2196
2197     size = sizeof(str_value);
2198     r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2200     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2201     ok(!strcmp(str_value, "Installer"),
2202        "Expected \"Installer\", got %s\n", str_value);
2203
2204     size = sizeof(str_value);
2205     r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2207     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2208     ok(!strcmp(str_value, "Installer comments"),
2209        "Expected \"Installer comments\", got %s\n", str_value);
2210
2211     size = sizeof(str_value);
2212     r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2213     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2214     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2215     ok(!strcmp(str_value, "Intel;1033,2057"),
2216        "Expected \"Intel;1033,2057\", got %s\n", str_value);
2217
2218     size = sizeof(str_value);
2219     r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2221     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2222     ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2223        "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2224
2225     r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2227     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2228
2229     r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2231     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2232
2233     r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2235     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2236     ok(int_value == 200, "Expected 200, got %d\n", int_value);
2237
2238     r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2240     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2241     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2242
2243     r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2245     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2246     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2247
2248     size = sizeof(str_value);
2249     r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2251     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2252     ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2253
2254     MsiCloseHandle(hsi);
2255     MsiCloseHandle(hdb);
2256     DeleteFileA(msifile);
2257 }
2258
2259 static void test_msiimport(void)
2260 {
2261     MSIHANDLE hdb, view, rec;
2262     LPCSTR query;
2263     UINT r, count;
2264     signed int i;
2265
2266     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2267
2268     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2270
2271     r = add_table_to_db(hdb, test_data);
2272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2273
2274     r = add_table_to_db(hdb, two_primary);
2275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2276
2277     r = add_table_to_db(hdb, endlines1);
2278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2279
2280     r = add_table_to_db(hdb, endlines2);
2281     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2282
2283     query = "SELECT * FROM `TestTable`";
2284     r = MsiDatabaseOpenView(hdb, query, &view);
2285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2286
2287     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2289     count = MsiRecordGetFieldCount(rec);
2290     ok(count == 9, "Expected 9, got %d\n", count);
2291     ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2292     ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2293     ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2294     ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2295     ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2296     ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2297     ok(check_record(rec, 7, "String"), "Expected String\n");
2298     ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2299     ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2300     MsiCloseHandle(rec);
2301
2302     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2304     count = MsiRecordGetFieldCount(rec);
2305     ok(count == 9, "Expected 9, got %d\n", count);
2306     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2307     ok(check_record(rec, 2, "i2"), "Expected i2\n");
2308     ok(check_record(rec, 3, "i2"), "Expected i2\n");
2309     ok(check_record(rec, 4, "I2"), "Expected I2\n");
2310     ok(check_record(rec, 5, "i4"), "Expected i4\n");
2311     ok(check_record(rec, 6, "I4"), "Expected I4\n");
2312     ok(check_record(rec, 7, "S255"), "Expected S255\n");
2313     ok(check_record(rec, 8, "S0"), "Expected S0\n");
2314     ok(check_record(rec, 9, "s0"), "Expected s0\n");
2315     MsiCloseHandle(rec);
2316
2317     query = "SELECT * FROM `TestTable`";
2318     r = do_query(hdb, query, &rec);
2319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2320     ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2321     ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2322     ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2323     ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2324
2325     i = MsiRecordGetInteger(rec, 2);
2326     ok(i == 5, "Expected 5, got %d\n", i);
2327
2328     i = MsiRecordGetInteger(rec, 3);
2329     ok(i == 2, "Expected 2, got %d\n", i);
2330
2331     i = MsiRecordGetInteger(rec, 4);
2332     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2333
2334     i = MsiRecordGetInteger(rec, 5);
2335     ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2336
2337     i = MsiRecordGetInteger(rec, 6);
2338     ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2339
2340     MsiCloseHandle(rec);
2341     MsiViewClose(view);
2342     MsiCloseHandle(view);
2343
2344     query = "SELECT * FROM `TwoPrimary`";
2345     r = MsiDatabaseOpenView(hdb, query, &view);
2346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2347
2348     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2350     count = MsiRecordGetFieldCount(rec);
2351     ok(count == 2, "Expected 2, got %d\n", count);
2352     ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2353     ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2354
2355     MsiCloseHandle(rec);
2356
2357     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2359     count = MsiRecordGetFieldCount(rec);
2360     ok(count == 2, "Expected 2, got %d\n", count);
2361     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2362     ok(check_record(rec, 2, "s255"), "Expected s255\n");
2363     MsiCloseHandle(rec);
2364
2365     r = MsiViewExecute(view, 0);
2366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2367
2368     r = MsiViewFetch(view, &rec);
2369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2370
2371     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2372     ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2373
2374     MsiCloseHandle(rec);
2375
2376     r = MsiViewFetch(view, &rec);
2377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2378
2379     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2380     ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2381
2382     MsiCloseHandle(rec);
2383
2384     r = MsiViewFetch(view, &rec);
2385     ok(r == ERROR_NO_MORE_ITEMS,
2386        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2387
2388     r = MsiViewClose(view);
2389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2390
2391     MsiCloseHandle(view);
2392
2393     query = "SELECT * FROM `Table`";
2394     r = MsiDatabaseOpenView(hdb, query, &view);
2395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2396
2397     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2399     count = MsiRecordGetFieldCount(rec);
2400     ok(count == 6, "Expected 6, got %d\n", count);
2401     ok(check_record(rec, 1, "A"), "Expected A\n");
2402     ok(check_record(rec, 2, "B"), "Expected B\n");
2403     ok(check_record(rec, 3, "C"), "Expected C\n");
2404     ok(check_record(rec, 4, "D"), "Expected D\n");
2405     ok(check_record(rec, 5, "E"), "Expected E\n");
2406     ok(check_record(rec, 6, "F"), "Expected F\n");
2407     MsiCloseHandle(rec);
2408
2409     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2411     count = MsiRecordGetFieldCount(rec);
2412     ok(count == 6, "Expected 6, got %d\n", count);
2413     ok(check_record(rec, 1, "s72"), "Expected s72\n");
2414     ok(check_record(rec, 2, "s72"), "Expected s72\n");
2415     ok(check_record(rec, 3, "s72"), "Expected s72\n");
2416     ok(check_record(rec, 4, "s72"), "Expected s72\n");
2417     ok(check_record(rec, 5, "s72"), "Expected s72\n");
2418     ok(check_record(rec, 6, "s72"), "Expected s72\n");
2419     MsiCloseHandle(rec);
2420
2421     MsiViewClose(view);
2422     MsiCloseHandle(view);
2423
2424     query = "SELECT * FROM `Table`";
2425     r = MsiDatabaseOpenView(hdb, query, &view);
2426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2427
2428     r = MsiViewExecute(view, 0);
2429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2430
2431     r = MsiViewFetch(view, &rec);
2432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2433     ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2434     ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2435     ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2436     ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2437     ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2438     ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2439
2440     MsiCloseHandle(rec);
2441
2442     r = MsiViewFetch(view, &rec);
2443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2444     ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2445     ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2446     ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2447     ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2448     ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2449     ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2450
2451     MsiCloseHandle(rec);
2452
2453     r = MsiViewFetch(view, &rec);
2454     ok(r == ERROR_NO_MORE_ITEMS,
2455        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2456
2457     MsiViewClose(view);
2458     MsiCloseHandle(view);
2459     MsiCloseHandle(hdb);
2460     DeleteFileA(msifile);
2461 }
2462
2463 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2464                                      "s72\tV0\r\n"
2465                                      "Binary\tName\r\n"
2466                                      "filename1\tfilename1.ibd\r\n";
2467
2468 static void test_binary_import(void)
2469 {
2470     MSIHANDLE hdb = 0, rec;
2471     char file[MAX_PATH];
2472     char buf[MAX_PATH];
2473     char path[MAX_PATH];
2474     DWORD size;
2475     LPCSTR query;
2476     UINT r;
2477
2478     /* create files to import */
2479     write_file("bin_import.idt", bin_import_dat,
2480           (sizeof(bin_import_dat) - 1) * sizeof(char));
2481     CreateDirectory("bin_import", NULL);
2482     create_file_data("bin_import/filename1.ibd", "just some words", 15);
2483
2484     /* import files into database */
2485     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
2486     ok( r == ERROR_SUCCESS , "Failed to open database\n");
2487
2488     GetCurrentDirectory(MAX_PATH, path);
2489     r = MsiDatabaseImport(hdb, path, "bin_import.idt");
2490     ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2491
2492     /* read file from the Binary table */
2493     query = "SELECT * FROM `Binary`";
2494     r = do_query(hdb, query, &rec);
2495     ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2496
2497     size = MAX_PATH;
2498     r = MsiRecordGetString(rec, 1, file, &size);
2499     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2500     ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file);
2501
2502     size = MAX_PATH;
2503     memset(buf, 0, MAX_PATH);
2504     r = MsiRecordReadStream(rec, 2, buf, &size);
2505     ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2506     ok(!lstrcmp(buf, "just some words"),
2507         "Expected 'just some words', got %s\n", buf);
2508
2509     r = MsiCloseHandle(rec);
2510     ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2511
2512     r = MsiCloseHandle(hdb);
2513     ok(r == ERROR_SUCCESS , "Failed to close database\n");
2514
2515     DeleteFile("bin_import/filename1.ibd");
2516     RemoveDirectory("bin_import");
2517     DeleteFile("bin_import.idt");
2518 }
2519
2520 static void test_markers(void)
2521 {
2522     MSIHANDLE hdb, rec;
2523     LPCSTR query;
2524     UINT r;
2525
2526     hdb = create_db();
2527     ok( hdb, "failed to create db\n");
2528
2529     rec = MsiCreateRecord(3);
2530     MsiRecordSetString(rec, 1, "Table");
2531     MsiRecordSetString(rec, 2, "Apples");
2532     MsiRecordSetString(rec, 3, "Oranges");
2533
2534     /* try a legit create */
2535     query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2536     r = run_query(hdb, 0, query);
2537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2538     MsiCloseHandle(rec);
2539
2540     /* try table name as marker */
2541     rec = MsiCreateRecord(1);
2542     MsiRecordSetString(rec, 1, "Fable");
2543     query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2544     r = run_query(hdb, rec, query);
2545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2546
2547     /* verify that we just created a table called '?', not 'Fable' */
2548     r = try_query(hdb, "SELECT * from `Fable`");
2549     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2550
2551     r = try_query(hdb, "SELECT * from `?`");
2552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2553
2554     /* try table name as marker without backticks */
2555     MsiRecordSetString(rec, 1, "Mable");
2556     query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2557     r = run_query(hdb, rec, query);
2558     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2559
2560     /* try one column name as marker */
2561     MsiRecordSetString(rec, 1, "One");
2562     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2563     r = run_query(hdb, rec, query);
2564     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2565     MsiCloseHandle(rec);
2566
2567     /* try column names as markers */
2568     rec = MsiCreateRecord(2);
2569     MsiRecordSetString(rec, 1, "One");
2570     MsiRecordSetString(rec, 2, "Two");
2571     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2572     r = run_query(hdb, rec, query);
2573     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2574     MsiCloseHandle(rec);
2575
2576     /* try names with backticks */
2577     rec = MsiCreateRecord(3);
2578     MsiRecordSetString(rec, 1, "One");
2579     MsiRecordSetString(rec, 2, "Two");
2580     MsiRecordSetString(rec, 3, "One");
2581     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2582     r = run_query(hdb, rec, query);
2583     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2584
2585     /* try names with backticks, minus definitions */
2586     query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2587     r = run_query(hdb, rec, query);
2588     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2589
2590     /* try names without backticks */
2591     query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2592     r = run_query(hdb, rec, query);
2593     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2594     MsiCloseHandle(rec);
2595
2596     /* try one long marker */
2597     rec = MsiCreateRecord(1);
2598     MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2599     query = "CREATE TABLE `Mable` ( ? )";
2600     r = run_query(hdb, rec, query);
2601     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2602     MsiCloseHandle(rec);
2603
2604     /* try all names as markers */
2605     rec = MsiCreateRecord(4);
2606     MsiRecordSetString(rec, 1, "Mable");
2607     MsiRecordSetString(rec, 2, "One");
2608     MsiRecordSetString(rec, 3, "Two");
2609     MsiRecordSetString(rec, 4, "One");
2610     query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) 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     MsiCloseHandle(rec);
2614
2615     /* try a legit insert */
2616     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2617     r = run_query(hdb, 0, query);
2618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2619
2620     r = try_query(hdb, "SELECT * from `Table`");
2621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2622
2623     /* try values as markers */
2624     rec = MsiCreateRecord(2);
2625     MsiRecordSetInteger(rec, 1, 4);
2626     MsiRecordSetString(rec, 2, "hi");
2627     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2628     r = run_query(hdb, rec, query);
2629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2630     MsiCloseHandle(rec);
2631
2632     /* try column names and values as markers */
2633     rec = MsiCreateRecord(4);
2634     MsiRecordSetString(rec, 1, "One");
2635     MsiRecordSetString(rec, 2, "Two");
2636     MsiRecordSetInteger(rec, 3, 5);
2637     MsiRecordSetString(rec, 4, "hi");
2638     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2639     r = run_query(hdb, rec, query);
2640     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2641     MsiCloseHandle(rec);
2642
2643     /* try column names as markers */
2644     rec = MsiCreateRecord(2);
2645     MsiRecordSetString(rec, 1, "One");
2646     MsiRecordSetString(rec, 2, "Two");
2647     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2648     r = run_query(hdb, rec, query);
2649     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2650     MsiCloseHandle(rec);
2651
2652     /* try table name as a marker */
2653     rec = MsiCreateRecord(1);
2654     MsiRecordSetString(rec, 1, "Table");
2655     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2656     r = run_query(hdb, rec, query);
2657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2658     MsiCloseHandle(rec);
2659
2660     /* try table name and values as markers */
2661     rec = MsiCreateRecord(3);
2662     MsiRecordSetString(rec, 1, "Table");
2663     MsiRecordSetInteger(rec, 2, 10);
2664     MsiRecordSetString(rec, 3, "haha");
2665     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2666     r = run_query(hdb, rec, query);
2667     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2668     MsiCloseHandle(rec);
2669
2670     /* try all markers */
2671     rec = MsiCreateRecord(5);
2672     MsiRecordSetString(rec, 1, "Table");
2673     MsiRecordSetString(rec, 1, "One");
2674     MsiRecordSetString(rec, 1, "Two");
2675     MsiRecordSetInteger(rec, 2, 10);
2676     MsiRecordSetString(rec, 3, "haha");
2677     query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2678     r = run_query(hdb, rec, query);
2679     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2680     MsiCloseHandle(rec);
2681
2682     /* insert an integer as a string */
2683     rec = MsiCreateRecord(2);
2684     MsiRecordSetString(rec, 1, "11");
2685     MsiRecordSetString(rec, 2, "hi");
2686     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2687     r = run_query(hdb, rec, query);
2688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2689     MsiCloseHandle(rec);
2690
2691     /* leave off the '' for the string */
2692     rec = MsiCreateRecord(2);
2693     MsiRecordSetInteger(rec, 1, 12);
2694     MsiRecordSetString(rec, 2, "hi");
2695     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2696     r = run_query(hdb, rec, query);
2697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2698     MsiCloseHandle(rec);
2699
2700     MsiCloseHandle(hdb);
2701     DeleteFileA(msifile);
2702 }
2703
2704 #define MY_NVIEWS 4000    /* Largest installer I've seen uses < 2k */
2705 static void test_handle_limit(void)
2706 {
2707     int i;
2708     MSIHANDLE hdb;
2709     MSIHANDLE hviews[MY_NVIEWS];
2710     UINT r;
2711
2712     /* create an empty db */
2713     hdb = create_db();
2714     ok( hdb, "failed to create db\n");
2715
2716     memset(hviews, 0, sizeof(hviews));
2717
2718     for (i=0; i<MY_NVIEWS; i++) {
2719         static char szQueryBuf[256] = "SELECT * from `_Tables`";
2720         hviews[i] = 0xdeadbeeb;
2721         r = MsiDatabaseOpenView(hdb, szQueryBuf, &hviews[i]);
2722         if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 
2723             hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2724             break;
2725     }
2726
2727     ok( i == MY_NVIEWS, "problem opening views\n");
2728
2729     for (i=0; i<MY_NVIEWS; i++) {
2730         if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2731             MsiViewClose(hviews[i]);
2732             r = MsiCloseHandle(hviews[i]);
2733             if (r != ERROR_SUCCESS)
2734                 break;
2735         }
2736     }
2737
2738     ok( i == MY_NVIEWS, "problem closing views\n");
2739
2740     r = MsiCloseHandle(hdb);
2741     ok( r == ERROR_SUCCESS, "failed to close database\n");
2742 }
2743
2744 static void generate_transform(void)
2745 {
2746     MSIHANDLE hdb1, hdb2, hrec;
2747     LPCSTR query;
2748     UINT r;
2749
2750     /* start with two identical databases */
2751     CopyFile(msifile2, msifile, FALSE);
2752
2753     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb1 );
2754     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2755
2756     r = MsiDatabaseCommit( hdb1 );
2757     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2758
2759     r = MsiOpenDatabase(msifile2, MSIDBOPEN_READONLY, &hdb2 );
2760     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2761
2762     /* the transform between two identical database should be empty */
2763     r = MsiDatabaseGenerateTransform(hdb1, hdb2, NULL, 0, 0);
2764     todo_wine {
2765     ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2766     }
2767
2768     query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2769     r = run_query(hdb1, 0, query);
2770     ok(r == ERROR_SUCCESS, "failed to add table\n");
2771
2772     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2773     r = run_query(hdb1, 0, query);
2774     ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2775
2776     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2777     r = run_query(hdb1, 0, query);
2778     ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2779
2780     query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2781     r = run_query(hdb1, 0, query);
2782     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2783
2784     query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2785     r = run_query(hdb1, 0, query);
2786     ok(r == ERROR_SUCCESS, "failed to delete row\n");
2787
2788     hrec = MsiCreateRecord(2);
2789     r = MsiRecordSetInteger(hrec, 1, 1);
2790     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2791
2792     write_file("testdata.bin", "naengmyon", 9);
2793     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
2794     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2795
2796     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2797     r = run_query(hdb1, hrec, query);
2798     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2799
2800     MsiCloseHandle(hrec);
2801
2802     query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2803     r = run_query(hdb1, 0, query);
2804     ok(r == ERROR_SUCCESS, "failed to add column\n");
2805
2806     query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2807     r = run_query(hdb1, 0, query);
2808     ok(r == ERROR_SUCCESS, "failed to add column\n");
2809
2810     query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2811     r = run_query(hdb1, 0, query);
2812     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2813
2814     query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2815             "`Value` CHAR(0) PRIMARY KEY `Property`)";
2816     r = run_query(hdb1, 0, query);
2817     ok(r == ERROR_SUCCESS, "failed to add property table\n");
2818
2819     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2820     r = run_query(hdb1, 0, query);
2821     ok(r == ERROR_SUCCESS, "failed to add property\n");
2822
2823     /* database needs to be committed */
2824     MsiDatabaseCommit(hdb1);
2825
2826     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2827     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2828
2829     MsiCloseHandle( hdb1 );
2830     MsiCloseHandle( hdb2 );
2831
2832     DeleteFile("testdata.bin");
2833 }
2834
2835 /* data for generating a transform */
2836
2837 /* tables transform names - encoded as they would be in an msi database file */
2838 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2839 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2840 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2841 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2842 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2843 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2844 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2845 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2846 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2847
2848 /* data in each table */
2849 static const WCHAR data1[] = { /* AAR */
2850     0x0201, 0x0008, 0x8001,  /* 0x0201 = add row (1), two shorts */
2851     0x0201, 0x0009, 0x8002,
2852 };
2853 static const WCHAR data2[] = { /* _Columns */
2854     0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2855     0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2856     0x0401, 0x0005, 0x0000, 0x0006, 0xbdff,  /* 0x0401 = add row (1), 4 shorts */
2857     0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2858     0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2859     0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2860 };
2861 static const WCHAR data3[] = { /* _Tables */
2862     0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2863     0x0101, 0x000a,
2864 };
2865 static const char data4[] = /* _StringData */
2866     "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval";  /* all the strings squashed together */
2867 static const WCHAR data5[] = { /* _StringPool */
2868 /*  len, refs */
2869     0,   0,    /* string 0 ''    */
2870     3,   2,    /* string 1 'MOO' */
2871     3,   1,    /* string 2 'COW' */
2872     3,   1,    /* string 3 'PIG' */
2873     1,   1,    /* string 4 'c'   */
2874     3,   3,    /* string 5 'AAR' */
2875     3,   1,    /* string 6 'CAR' */
2876     3,   1,    /* string 7 'BAR' */
2877     2,   1,    /* string 8 'vw'  */
2878     3,   1,    /* string 9 'bmw' */
2879     8,   4,    /* string 10 'Property' */
2880     5,   1,    /* string 11 'Value' */
2881     4,   1,    /* string 12 'prop' */
2882     3,   1,    /* string 13 'val' */
2883 };
2884 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2885 static const WCHAR data6[] = { /* MOO */
2886     0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2887     0x0000, 0x8003,         /* delete row */
2888 };
2889
2890 static const WCHAR data7[] = { /* BINARY */
2891     0x0201, 0x8001, 0x0001,
2892 };
2893
2894 static const char data8[] =  /* stream data for the BINARY table */
2895     "naengmyon";
2896
2897 static const WCHAR data9[] = { /* Property */
2898     0x0201, 0x000c, 0x000d,
2899 };
2900
2901 static const struct {
2902     LPCWSTR name;
2903     const void *data;
2904     DWORD size;
2905 } table_transform_data[] =
2906 {
2907     { name1, data1, sizeof data1 },
2908     { name2, data2, sizeof data2 },
2909     { name3, data3, sizeof data3 },
2910     { name4, data4, sizeof data4 - 1 },
2911     { name5, data5, sizeof data5 },
2912     { name6, data6, sizeof data6 },
2913     { name7, data7, sizeof data7 },
2914     { name8, data8, sizeof data8 - 1 },
2915     { name9, data9, sizeof data9 },
2916 };
2917
2918 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2919
2920 static void generate_transform_manual(void)
2921 {
2922     IStorage *stg = NULL;
2923     IStream *stm;
2924     WCHAR name[0x20];
2925     HRESULT r;
2926     DWORD i, count;
2927     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2928
2929     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2930
2931     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2932
2933     r = StgCreateDocfile(name, mode, 0, &stg);
2934     ok(r == S_OK, "failed to create storage\n");
2935     if (!stg)
2936         return;
2937
2938     r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2939     ok(r == S_OK, "failed to set storage type\n");
2940
2941     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2942     {
2943         r = IStorage_CreateStream( stg, table_transform_data[i].name,
2944                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2945         if (FAILED(r))
2946         {
2947             ok(0, "failed to create stream %08x\n", r);
2948             continue;
2949         }
2950
2951         r = IStream_Write( stm, table_transform_data[i].data,
2952                           table_transform_data[i].size, &count );
2953         if (FAILED(r) || count != table_transform_data[i].size)
2954             ok(0, "failed to write stream\n");
2955         IStream_Release(stm);
2956     }
2957
2958     IStorage_Release(stg);
2959 }
2960
2961 static UINT set_summary_info(MSIHANDLE hdb)
2962 {
2963     UINT res;
2964     MSIHANDLE suminfo;
2965
2966     /* build summary info */
2967     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
2968     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2969
2970     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
2971                         "Installation Database");
2972     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2973
2974     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
2975                         "Installation Database");
2976     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2977
2978     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
2979                         "Wine Hackers");
2980     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2981
2982     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
2983                     ";1033,2057");
2984     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2985
2986     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
2987                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
2988     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2989
2990     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
2991     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2992
2993     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
2994     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2995
2996     res = MsiSummaryInfoPersist(suminfo);
2997     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
2998
2999     res = MsiCloseHandle( suminfo);
3000     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
3001
3002     return res;
3003 }
3004
3005 static MSIHANDLE create_package_db(LPCSTR filename)
3006 {
3007     MSIHANDLE hdb = 0;
3008     UINT res;
3009
3010     DeleteFile(msifile);
3011
3012     /* create an empty database */
3013     res = MsiOpenDatabase(filename, MSIDBOPEN_CREATE, &hdb );
3014     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
3015     if( res != ERROR_SUCCESS )
3016         return hdb;
3017
3018     res = MsiDatabaseCommit( hdb );
3019     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
3020
3021     res = set_summary_info(hdb);
3022     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3023
3024     res = create_directory_table(hdb);
3025     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
3026
3027     return hdb;
3028 }
3029
3030 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
3031 {
3032     UINT res;
3033     CHAR szPackage[12];
3034     MSIHANDLE hPackage;
3035
3036     sprintf(szPackage, "#%u", hdb);
3037     res = MsiOpenPackage(szPackage, &hPackage);
3038     if (res != ERROR_SUCCESS)
3039         return res;
3040
3041     res = MsiCloseHandle(hdb);
3042     if (res != ERROR_SUCCESS)
3043     {
3044         MsiCloseHandle(hPackage);
3045         return res;
3046     }
3047
3048     *handle = hPackage;
3049     return ERROR_SUCCESS;
3050 }
3051
3052 static void test_try_transform(void)
3053 {
3054     MSIHANDLE hdb, hview, hrec, hpkg = 0;
3055     LPCSTR query;
3056     UINT r;
3057     DWORD sz;
3058     char buffer[MAX_PATH];
3059
3060     DeleteFile(msifile);
3061     DeleteFile(mstfile);
3062
3063     /* create the database */
3064     hdb = create_package_db(msifile);
3065     ok(hdb, "Failed to create package db\n");
3066
3067     query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
3068     r = run_query(hdb, 0, query);
3069     ok(r == ERROR_SUCCESS, "failed to add table\n");
3070
3071     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
3072     r = run_query(hdb, 0, query);
3073     ok(r == ERROR_SUCCESS, "failed to add row\n");
3074
3075     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
3076     r = run_query(hdb, 0, query);
3077     ok(r == ERROR_SUCCESS, "failed to add row\n");
3078
3079     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
3080     r = run_query(hdb, 0, query);
3081     ok(r == ERROR_SUCCESS, "failed to add row\n");
3082
3083     query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
3084     r = run_query(hdb, 0, query);
3085     ok(r == ERROR_SUCCESS, "failed to add table\n");
3086
3087     hrec = MsiCreateRecord(2);
3088     r = MsiRecordSetInteger(hrec, 1, 2);
3089     ok(r == ERROR_SUCCESS, "failed to set integer\n");
3090
3091     write_file("testdata.bin", "lamyon", 6);
3092     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
3093     ok(r == ERROR_SUCCESS, "failed to set stream\n");
3094
3095     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3096     r = run_query(hdb, hrec, query);
3097     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3098
3099     MsiCloseHandle(hrec);
3100
3101     r = MsiDatabaseCommit( hdb );
3102     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3103
3104     MsiCloseHandle( hdb );
3105     DeleteFileA("testdata.bin");
3106
3107     /*
3108      * Both these generate an equivalent transform,
3109      *  but the first doesn't work in Wine yet
3110      *  because MsiDatabaseGenerateTransform is unimplemented.
3111      */
3112     if (0)
3113         generate_transform();
3114     else
3115         generate_transform_manual();
3116
3117     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb );
3118     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3119
3120     r = MsiDatabaseApplyTransform( hdb, mstfile, 0 );
3121     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3122
3123     MsiDatabaseCommit( hdb );
3124
3125     /* check new values */
3126     hrec = 0;
3127     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3128     r = do_query(hdb, query, &hrec);
3129     ok(r == ERROR_SUCCESS, "select query failed\n");
3130     MsiCloseHandle(hrec);
3131
3132     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3133     hrec = 0;
3134     r = do_query(hdb, query, &hrec);
3135     ok(r == ERROR_SUCCESS, "select query failed\n");
3136     MsiCloseHandle(hrec);
3137
3138     /* check updated values */
3139     hrec = 0;
3140     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3141     r = do_query(hdb, query, &hrec);
3142     ok(r == ERROR_SUCCESS, "select query failed\n");
3143     MsiCloseHandle(hrec);
3144
3145     /* check unchanged value */
3146     hrec = 0;
3147     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3148     r = do_query(hdb, query, &hrec);
3149     ok(r == ERROR_SUCCESS, "select query failed\n");
3150     MsiCloseHandle(hrec);
3151
3152     /* check deleted value */
3153     hrec = 0;
3154     query = "select * from `MOO` where `NOO` = 3";
3155     r = do_query(hdb, query, &hrec);
3156     ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3157     if (hrec) MsiCloseHandle(hrec);
3158
3159     /* check added stream */
3160     hrec = 0;
3161     query = "select `BLOB` from `BINARY` where `ID` = 1";
3162     r = do_query(hdb, query, &hrec);
3163     ok(r == ERROR_SUCCESS, "select query failed\n");
3164
3165     /* check the contents of the stream */
3166     sz = sizeof buffer;
3167     r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3168     ok(r == ERROR_SUCCESS, "read stream failed\n");
3169     ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3170     ok(sz == 9, "stream data was wrong size\n");
3171     if (hrec) MsiCloseHandle(hrec);
3172
3173     /* check the validity of the table with a deleted row */
3174     hrec = 0;
3175     query = "select * from `MOO`";
3176     r = MsiDatabaseOpenView(hdb, query, &hview);
3177     ok(r == ERROR_SUCCESS, "open view failed\n");
3178
3179     r = MsiViewExecute(hview, 0);
3180     ok(r == ERROR_SUCCESS, "view execute failed\n");
3181
3182     r = MsiViewFetch(hview, &hrec);
3183     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3184
3185     r = MsiRecordGetInteger(hrec, 1);
3186     ok(r == 1, "Expected 1, got %d\n", r);
3187
3188     sz = sizeof buffer;
3189     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3190     ok(r == ERROR_SUCCESS, "record get string failed\n");
3191     ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3192
3193     r = MsiRecordGetInteger(hrec, 3);
3194     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3195
3196     r = MsiRecordGetInteger(hrec, 4);
3197     ok(r == 5, "Expected 5, got %d\n", r);
3198
3199     MsiCloseHandle(hrec);
3200
3201     r = MsiViewFetch(hview, &hrec);
3202     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3203
3204     r = MsiRecordGetInteger(hrec, 1);
3205     ok(r == 2, "Expected 2, got %d\n", r);
3206
3207     sz = sizeof buffer;
3208     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3209     ok(r == ERROR_SUCCESS, "record get string failed\n");
3210     ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3211
3212     r = MsiRecordGetInteger(hrec, 3);
3213     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3214
3215     r = MsiRecordGetInteger(hrec, 4);
3216     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3217
3218     MsiCloseHandle(hrec);
3219
3220     r = MsiViewFetch(hview, &hrec);
3221     ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3222
3223     MsiCloseHandle(hrec);
3224     MsiViewClose(hview);
3225     MsiCloseHandle(hview);
3226
3227     /* check that the property was added */
3228     r = package_from_db(hdb, &hpkg);
3229     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3230     {
3231         skip("Not enough rights to perform tests\n");
3232         goto error;
3233     }
3234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3235
3236     sz = MAX_PATH;
3237     r = MsiGetProperty(hpkg, "prop", buffer, &sz);
3238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3239     ok(!lstrcmp(buffer, "val"), "Expected val, got %s\n", buffer);
3240
3241     MsiCloseHandle(hpkg);
3242
3243 error:
3244     MsiCloseHandle(hdb);
3245     DeleteFile(msifile);
3246     DeleteFile(mstfile);
3247 }
3248
3249 struct join_res
3250 {
3251     const CHAR one[MAX_PATH];
3252     const CHAR two[MAX_PATH];
3253 };
3254
3255 struct join_res_4col
3256 {
3257     const CHAR one[MAX_PATH];
3258     const CHAR two[MAX_PATH];
3259     const CHAR three[MAX_PATH];
3260     const CHAR four[MAX_PATH];
3261 };
3262
3263 struct join_res_uint
3264 {
3265     UINT one;
3266     UINT two;
3267     UINT three;
3268     UINT four;
3269     UINT five;
3270     UINT six;
3271 };
3272
3273 static const struct join_res join_res_first[] =
3274 {
3275     { "alveolar", "procerus" },
3276     { "septum", "procerus" },
3277     { "septum", "nasalis" },
3278     { "ramus", "nasalis" },
3279     { "malar", "mentalis" },
3280 };
3281
3282 static const struct join_res join_res_second[] =
3283 {
3284     { "nasal", "septum" },
3285     { "mandible", "ramus" },
3286 };
3287
3288 static const struct join_res join_res_third[] =
3289 {
3290     { "msvcp.dll", "abcdefgh" },
3291     { "msvcr.dll", "ijklmnop" },
3292 };
3293
3294 static const struct join_res join_res_fourth[] =
3295 {
3296     { "msvcp.dll.01234", "single.dll.31415" },
3297 };
3298
3299 static const struct join_res join_res_fifth[] =
3300 {
3301     { "malar", "procerus" },
3302 };
3303
3304 static const struct join_res join_res_sixth[] =
3305 {
3306     { "malar", "procerus" },
3307     { "malar", "procerus" },
3308     { "malar", "nasalis" },
3309     { "malar", "nasalis" },
3310     { "malar", "nasalis" },
3311     { "malar", "mentalis" },
3312 };
3313
3314 static const struct join_res join_res_seventh[] =
3315 {
3316     { "malar", "nasalis" },
3317     { "malar", "nasalis" },
3318     { "malar", "nasalis" },
3319 };
3320
3321 static const struct join_res_4col join_res_eighth[] =
3322 {
3323     { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3324     { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3325     { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3326     { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3327     { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3328     { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3329 };
3330
3331 static const struct join_res_uint join_res_ninth[] =
3332 {
3333     { 1, 2, 3, 4, 7, 8 },
3334     { 1, 2, 5, 6, 7, 8 },
3335     { 1, 2, 3, 4, 9, 10 },
3336     { 1, 2, 5, 6, 9, 10 },
3337     { 1, 2, 3, 4, 11, 12 },
3338     { 1, 2, 5, 6, 11, 12 },
3339 };
3340
3341 static void test_join(void)
3342 {
3343     MSIHANDLE hdb, hview, hrec;
3344     LPCSTR query;
3345     CHAR buf[MAX_PATH];
3346     UINT r, count;
3347     DWORD size, i;
3348     BOOL data_correct;
3349
3350     hdb = create_db();
3351     ok( hdb, "failed to create db\n");
3352
3353     r = create_component_table( hdb );
3354     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3355
3356     r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3357     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3358
3359     r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3360     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3361
3362     r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3363     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3364
3365     r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3366     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3367
3368     r = create_feature_components_table( hdb );
3369     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3370
3371     r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3372     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3373
3374     r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3375     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3376
3377     r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3378     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3379
3380     r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3381     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3382
3383     r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3384     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3385
3386     r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3387     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3388
3389     r = create_std_dlls_table( hdb );
3390     ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3391
3392     r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3393     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3394
3395     r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3396     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3397
3398     r = create_binary_table( hdb );
3399     ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3400
3401     r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3402     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3403
3404     r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3405     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3406
3407     r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3408     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3409
3410     query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3411     r = run_query( hdb, 0, query);
3412     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3413
3414     query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3415     r = run_query( hdb, 0, query);
3416     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3417
3418     query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3419     r = run_query( hdb, 0, query);
3420     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3421
3422     query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3423     r = run_query( hdb, 0, query);
3424     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3425
3426     query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3427     r = run_query( hdb, 0, query);
3428     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3429
3430     query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3431     r = run_query( hdb, 0, query);
3432     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3433
3434     query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3435     r = run_query( hdb, 0, query);
3436     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3437
3438     query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3439     r = run_query( hdb, 0, query);
3440     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3441
3442     query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3443     r = run_query( hdb, 0, query);
3444     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3445
3446     query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3447     r = run_query( hdb, 0, query);
3448     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3449
3450     query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3451     r = run_query( hdb, 0, query);
3452     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3453
3454     query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3455     r = run_query( hdb, 0, query);
3456     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3457
3458     query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3459     r = run_query( hdb, 0, query);
3460     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3461
3462     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3463             "FROM `Component`, `FeatureComponents` "
3464             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3465             "ORDER BY `Feature_`";
3466     r = MsiDatabaseOpenView(hdb, query, &hview);
3467     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3468
3469     r = MsiViewExecute(hview, 0);
3470     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3471
3472     i = 0;
3473     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3474     {
3475         count = MsiRecordGetFieldCount( hrec );
3476         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3477
3478         size = MAX_PATH;
3479         r = MsiRecordGetString( hrec, 1, buf, &size );
3480         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3481         ok( !lstrcmp( buf, join_res_first[i].one ),
3482             "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3483
3484         size = MAX_PATH;
3485         r = MsiRecordGetString( hrec, 2, buf, &size );
3486         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3487         ok( !lstrcmp( buf, join_res_first[i].two ),
3488             "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3489
3490         i++;
3491         MsiCloseHandle(hrec);
3492     }
3493
3494     ok( i == 5, "Expected 5 rows, got %d\n", i );
3495     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3496
3497     MsiViewClose(hview);
3498     MsiCloseHandle(hview);
3499
3500     /* try a join without a WHERE condition */
3501     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3502             "FROM `Component`, `FeatureComponents` ";
3503     r = MsiDatabaseOpenView(hdb, query, &hview);
3504     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3505
3506     r = MsiViewExecute(hview, 0);
3507     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3508
3509     i = 0;
3510     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3511     {
3512         i++;
3513         MsiCloseHandle(hrec);
3514     }
3515     ok( i == 24, "Expected 24 rows, got %d\n", i );
3516
3517     MsiViewClose(hview);
3518     MsiCloseHandle(hview);
3519
3520     query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3521             "WHERE FeatureComponents.Component_=Component.Component "
3522             "AND (Feature_='nasalis') ORDER BY Feature_";
3523     r = MsiDatabaseOpenView(hdb, query, &hview);
3524     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3525
3526     r = MsiViewExecute(hview, 0);
3527     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3528
3529     i = 0;
3530     data_correct = TRUE;
3531     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3532     {
3533         count = MsiRecordGetFieldCount( hrec );
3534         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3535
3536         size = MAX_PATH;
3537         r = MsiRecordGetString( hrec, 1, buf, &size );
3538         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3539         if( lstrcmp( buf, join_res_second[i].one ))
3540             data_correct = FALSE;
3541
3542         size = MAX_PATH;
3543         r = MsiRecordGetString( hrec, 2, buf, &size );
3544         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3545         if( lstrcmp( buf, join_res_second[i].two ))
3546             data_correct = FALSE;
3547
3548         i++;
3549         MsiCloseHandle(hrec);
3550     }
3551
3552     ok( data_correct, "data returned in the wrong order\n");
3553
3554     ok( i == 2, "Expected 2 rows, got %d\n", i );
3555     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3556
3557     MsiViewClose(hview);
3558     MsiCloseHandle(hview);
3559
3560     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3561             "FROM `StdDlls`, `Binary` "
3562             "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3563             "ORDER BY `File`";
3564     r = MsiDatabaseOpenView(hdb, query, &hview);
3565     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3566
3567     r = MsiViewExecute(hview, 0);
3568     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3569
3570     i = 0;
3571     data_correct = TRUE;
3572     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3573     {
3574         count = MsiRecordGetFieldCount( hrec );
3575         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3576
3577         size = MAX_PATH;
3578         r = MsiRecordGetString( hrec, 1, buf, &size );
3579         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3580         if( lstrcmp( buf, join_res_third[i].one ) )
3581             data_correct = FALSE;
3582
3583         size = MAX_PATH;
3584         r = MsiRecordGetString( hrec, 2, buf, &size );
3585         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3586         if( lstrcmp( buf, join_res_third[i].two ) )
3587             data_correct = FALSE;
3588
3589         i++;
3590         MsiCloseHandle(hrec);
3591     }
3592     ok( data_correct, "data returned in the wrong order\n");
3593
3594     ok( i == 2, "Expected 2 rows, got %d\n", i );
3595
3596     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3597
3598     MsiViewClose(hview);
3599     MsiCloseHandle(hview);
3600
3601     query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3602             "FROM `StdDlls`, `Binary` "
3603             "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3604             "ORDER BY `Name`";
3605     r = MsiDatabaseOpenView(hdb, query, &hview);
3606     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3607
3608     r = MsiViewExecute(hview, 0);
3609     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3610
3611     i = 0;
3612     data_correct = TRUE;
3613     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3614     {
3615         count = MsiRecordGetFieldCount( hrec );
3616         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3617
3618         size = MAX_PATH;
3619         r = MsiRecordGetString( hrec, 1, buf, &size );
3620         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3621         if( lstrcmp( buf, join_res_fourth[i].one ))
3622             data_correct = FALSE;
3623
3624         size = MAX_PATH;
3625         r = MsiRecordGetString( hrec, 2, buf, &size );
3626         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3627         if( lstrcmp( buf, join_res_fourth[i].two ))
3628             data_correct = FALSE;
3629
3630         i++;
3631         MsiCloseHandle(hrec);
3632     }
3633     ok( data_correct, "data returned in the wrong order\n");
3634
3635     ok( i == 1, "Expected 1 rows, got %d\n", i );
3636     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3637
3638     MsiViewClose(hview);
3639     MsiCloseHandle(hview);
3640
3641     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3642             "FROM `Component`, `FeatureComponents` "
3643             "WHERE `Component`.`Component` = 'zygomatic' "
3644             "AND `FeatureComponents`.`Component_` = 'maxilla' "
3645             "ORDER BY `Feature_`";
3646     r = MsiDatabaseOpenView(hdb, query, &hview);
3647     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3648
3649     r = MsiViewExecute(hview, 0);
3650     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3651
3652     i = 0;
3653     data_correct = TRUE;
3654     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3655     {
3656         count = MsiRecordGetFieldCount( hrec );
3657         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3658
3659         size = MAX_PATH;
3660         r = MsiRecordGetString( hrec, 1, buf, &size );
3661         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3662         if( lstrcmp( buf, join_res_fifth[i].one ))
3663             data_correct = FALSE;
3664
3665         size = MAX_PATH;
3666         r = MsiRecordGetString( hrec, 2, buf, &size );
3667         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3668         if( lstrcmp( buf, join_res_fifth[i].two ))
3669             data_correct = FALSE;
3670
3671         i++;
3672         MsiCloseHandle(hrec);
3673     }
3674     ok( data_correct, "data returned in the wrong order\n");
3675
3676     ok( i == 1, "Expected 1 rows, got %d\n", i );
3677     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3678
3679     MsiViewClose(hview);
3680     MsiCloseHandle(hview);
3681
3682     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3683             "FROM `Component`, `FeatureComponents` "
3684             "WHERE `Component` = 'zygomatic' "
3685             "ORDER BY `Feature_`";
3686     r = MsiDatabaseOpenView(hdb, query, &hview);
3687     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3688
3689     r = MsiViewExecute(hview, 0);
3690     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3691
3692     i = 0;
3693     data_correct = TRUE;
3694     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3695     {
3696         count = MsiRecordGetFieldCount( hrec );
3697         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3698
3699         size = MAX_PATH;
3700         r = MsiRecordGetString( hrec, 1, buf, &size );
3701         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3702         if( lstrcmp( buf, join_res_sixth[i].one ))
3703             data_correct = FALSE;
3704
3705         size = MAX_PATH;
3706         r = MsiRecordGetString( hrec, 2, buf, &size );
3707         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3708         if( lstrcmp( buf, join_res_sixth[i].two ))
3709             data_correct = FALSE;
3710
3711         i++;
3712         MsiCloseHandle(hrec);
3713     }
3714     ok( data_correct, "data returned in the wrong order\n");
3715
3716     ok( i == 6, "Expected 6 rows, got %d\n", i );
3717     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3718
3719     MsiViewClose(hview);
3720     MsiCloseHandle(hview);
3721
3722     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3723             "FROM `Component`, `FeatureComponents` "
3724             "WHERE `Component` = 'zygomatic' "
3725             "AND `Feature_` = 'nasalis' "
3726             "ORDER BY `Feature_`";
3727     r = MsiDatabaseOpenView(hdb, query, &hview);
3728     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3729
3730     r = MsiViewExecute(hview, 0);
3731     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3732
3733     i = 0;
3734     data_correct = TRUE;
3735     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3736     {
3737         count = MsiRecordGetFieldCount( hrec );
3738         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3739
3740         size = MAX_PATH;
3741         r = MsiRecordGetString( hrec, 1, buf, &size );
3742         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3743         if( lstrcmp( buf, join_res_seventh[i].one ))
3744             data_correct = FALSE;
3745
3746         size = MAX_PATH;
3747         r = MsiRecordGetString( hrec, 2, buf, &size );
3748         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3749         if( lstrcmp( buf, join_res_seventh[i].two ))
3750             data_correct = FALSE;
3751
3752         i++;
3753         MsiCloseHandle(hrec);
3754     }
3755
3756     ok( data_correct, "data returned in the wrong order\n");
3757     ok( i == 3, "Expected 3 rows, got %d\n", i );
3758     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3759
3760     MsiViewClose(hview);
3761     MsiCloseHandle(hview);
3762
3763     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3764             "FROM `StdDlls`, `Binary` ";
3765     r = MsiDatabaseOpenView(hdb, query, &hview);
3766     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3767
3768     r = MsiViewExecute(hview, 0);
3769     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3770
3771     i = 0;
3772     data_correct = TRUE;
3773     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3774     {
3775         count = MsiRecordGetFieldCount( hrec );
3776         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3777
3778         size = MAX_PATH;
3779         r = MsiRecordGetString( hrec, 1, buf, &size );
3780         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3781         if( lstrcmp( buf, join_res_eighth[i].one ))
3782             data_correct = FALSE;
3783
3784         size = MAX_PATH;
3785         r = MsiRecordGetString( hrec, 2, buf, &size );
3786         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3787         if( lstrcmp( buf, join_res_eighth[i].four ))
3788             data_correct = FALSE;
3789
3790         i++;
3791         MsiCloseHandle(hrec);
3792     }
3793
3794     ok( data_correct, "data returned in the wrong order\n");
3795     ok( i == 6, "Expected 6 rows, got %d\n", i );
3796     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3797
3798     MsiViewClose(hview);
3799     MsiCloseHandle(hview);
3800
3801     query = "SELECT * FROM `StdDlls`, `Binary` ";
3802     r = MsiDatabaseOpenView(hdb, query, &hview);
3803     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3804
3805     r = MsiViewExecute(hview, 0);
3806     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3807
3808     i = 0;
3809     data_correct = TRUE;
3810     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3811     {
3812         count = MsiRecordGetFieldCount( hrec );
3813         ok( count == 4, "Expected 4 record fields, got %d\n", count );
3814
3815         size = MAX_PATH;
3816         r = MsiRecordGetString( hrec, 1, buf, &size );
3817         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3818         if( lstrcmp( buf, join_res_eighth[i].one ))
3819             data_correct = FALSE;
3820
3821         size = MAX_PATH;
3822         r = MsiRecordGetString( hrec, 2, buf, &size );
3823         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3824         if( lstrcmp( buf, join_res_eighth[i].two ))
3825             data_correct = FALSE;
3826
3827         size = MAX_PATH;
3828         r = MsiRecordGetString( hrec, 3, buf, &size );
3829         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3830         if( lstrcmp( buf, join_res_eighth[i].three ))
3831             data_correct = FALSE;
3832
3833         size = MAX_PATH;
3834         r = MsiRecordGetString( hrec, 4, buf, &size );
3835         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3836         if( lstrcmp( buf, join_res_eighth[i].four ))
3837             data_correct = FALSE;
3838
3839         i++;
3840         MsiCloseHandle(hrec);
3841     }
3842     ok( data_correct, "data returned in the wrong order\n");
3843
3844     ok( i == 6, "Expected 6 rows, got %d\n", i );
3845     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3846
3847     MsiViewClose(hview);
3848     MsiCloseHandle(hview);
3849
3850     query = "SELECT * FROM `One`, `Two`, `Three` ";
3851     r = MsiDatabaseOpenView(hdb, query, &hview);
3852     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3853
3854     r = MsiViewExecute(hview, 0);
3855     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3856
3857     i = 0;
3858     data_correct = TRUE;
3859     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3860     {
3861         count = MsiRecordGetFieldCount( hrec );
3862         ok( count == 6, "Expected 6 record fields, got %d\n", count );
3863
3864         r = MsiRecordGetInteger( hrec, 1 );
3865         if( r != join_res_ninth[i].one )
3866             data_correct = FALSE;
3867
3868         r = MsiRecordGetInteger( hrec, 2 );
3869         if( r != join_res_ninth[i].two )
3870             data_correct = FALSE;
3871
3872         r = MsiRecordGetInteger( hrec, 3 );
3873         if( r != join_res_ninth[i].three )
3874             data_correct = FALSE;
3875
3876         r = MsiRecordGetInteger( hrec, 4 );
3877         if( r != join_res_ninth[i].four )
3878             data_correct = FALSE;
3879
3880         r = MsiRecordGetInteger( hrec, 5 );
3881         if( r != join_res_ninth[i].five )
3882             data_correct = FALSE;
3883
3884         r = MsiRecordGetInteger( hrec, 6);
3885         if( r != join_res_ninth[i].six )
3886             data_correct = FALSE;
3887
3888         i++;
3889         MsiCloseHandle(hrec);
3890     }
3891     ok( data_correct, "data returned in the wrong order\n");
3892
3893     ok( i == 6, "Expected 6 rows, got %d\n", i );
3894     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3895
3896     MsiViewClose(hview);
3897     MsiCloseHandle(hview);
3898
3899     query = "SELECT * FROM `Four`, `Five`";
3900     r = MsiDatabaseOpenView(hdb, query, &hview);
3901     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3902
3903     r = MsiViewExecute(hview, 0);
3904     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3905
3906     r = MsiViewFetch(hview, &hrec);
3907     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3908
3909     MsiViewClose(hview);
3910     MsiCloseHandle(hview);
3911
3912     query = "SELECT * FROM `Nonexistent`, `One`";
3913     r = MsiDatabaseOpenView(hdb, query, &hview);
3914     ok( r == ERROR_BAD_QUERY_SYNTAX,
3915         "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3916
3917     /* try updating a row in a join table */
3918     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3919             "FROM `Component`, `FeatureComponents` "
3920             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3921             "ORDER BY `Feature_`";
3922     r = MsiDatabaseOpenView(hdb, query, &hview);
3923     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3924
3925     r = MsiViewExecute(hview, 0);
3926     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3927
3928     r = MsiViewFetch(hview, &hrec);
3929     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3930
3931     r = MsiRecordSetString( hrec, 1, "epicranius" );
3932     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3933
3934     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3935     ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3936
3937     /* try another valid operation for joins */
3938     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3939     todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3940
3941     /* try an invalid operation for joins */
3942     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3943     ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3944
3945     r = MsiRecordSetString( hrec, 2, "epicranius" );
3946     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3947
3948     /* primary key cannot be updated */
3949     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3950     ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3951
3952     MsiCloseHandle(hrec);
3953     MsiViewClose(hview);
3954     MsiCloseHandle(hview);
3955
3956     r = MsiDatabaseOpenView(hdb, query, &hview);
3957     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3958
3959     r = MsiViewExecute(hview, 0);
3960     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3961
3962     r = MsiViewFetch(hview, &hrec);
3963     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3964
3965     size = MAX_PATH;
3966     r = MsiRecordGetString( hrec, 1, buf, &size );
3967     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3968     ok( !lstrcmp( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
3969
3970     MsiCloseHandle(hrec);
3971     MsiViewClose(hview);
3972     MsiCloseHandle(hview);
3973
3974     MsiCloseHandle(hdb);
3975     DeleteFile(msifile);
3976 }
3977
3978 static void test_temporary_table(void)
3979 {
3980     MSICONDITION cond;
3981     MSIHANDLE hdb = 0, view = 0, rec;
3982     const char *query;
3983     UINT r;
3984     char buf[0x10];
3985     DWORD sz;
3986
3987     cond = MsiDatabaseIsTablePersistent(0, NULL);
3988     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3989
3990     hdb = create_db();
3991     ok( hdb, "failed to create db\n");
3992
3993     cond = MsiDatabaseIsTablePersistent(hdb, NULL);
3994     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3995
3996     cond = MsiDatabaseIsTablePersistent(hdb, "_Tables");
3997     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3998
3999     cond = MsiDatabaseIsTablePersistent(hdb, "_Columns");
4000     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4001
4002     cond = MsiDatabaseIsTablePersistent(hdb, "_Storages");
4003     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4004
4005     cond = MsiDatabaseIsTablePersistent(hdb, "_Streams");
4006     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4007
4008     query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
4009     r = run_query(hdb, 0, query);
4010     ok(r == ERROR_SUCCESS, "failed to add table\n");
4011
4012     cond = MsiDatabaseIsTablePersistent(hdb, "P");
4013     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4014
4015     query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
4016     r = run_query(hdb, 0, query);
4017     ok(r == ERROR_SUCCESS, "failed to add table\n");
4018
4019     cond = MsiDatabaseIsTablePersistent(hdb, "P2");
4020     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4021
4022     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4023     r = run_query(hdb, 0, query);
4024     ok(r == ERROR_SUCCESS, "failed to add table\n");
4025
4026     cond = MsiDatabaseIsTablePersistent(hdb, "T");
4027     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4028
4029     query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4030     r = run_query(hdb, 0, query);
4031     ok(r == ERROR_SUCCESS, "failed to add table\n");
4032
4033     query = "SELECT * FROM `T2`";
4034     r = MsiDatabaseOpenView(hdb, query, &view);
4035     ok(r == ERROR_BAD_QUERY_SYNTAX,
4036        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4037
4038     cond = MsiDatabaseIsTablePersistent(hdb, "T2");
4039     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4040
4041     query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
4042     r = run_query(hdb, 0, query);
4043     ok(r == ERROR_SUCCESS, "failed to add table\n");
4044
4045     cond = MsiDatabaseIsTablePersistent(hdb, "T3");
4046     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4047
4048     query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4049     r = run_query(hdb, 0, query);
4050     ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
4051
4052     cond = MsiDatabaseIsTablePersistent(hdb, "T4");
4053     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4054
4055     query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
4056     r = run_query(hdb, 0, query);
4057     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
4058
4059     query = "select * from `T`";
4060     r = MsiDatabaseOpenView(hdb, query, &view);
4061     ok(r == ERROR_SUCCESS, "failed to query table\n");
4062     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4063     ok(r == ERROR_SUCCESS, "failed to get column info\n");
4064
4065     sz = sizeof buf;
4066     r = MsiRecordGetString(rec, 1, buf, &sz);
4067     ok(r == ERROR_SUCCESS, "failed to get string\n");
4068     ok( 0 == strcmp("G255", buf), "wrong column type\n");
4069
4070     sz = sizeof buf;
4071     r = MsiRecordGetString(rec, 2, buf, &sz);
4072     ok(r == ERROR_SUCCESS, "failed to get string\n");
4073     ok( 0 == strcmp("j2", buf), "wrong column type\n");
4074
4075     MsiCloseHandle( rec );
4076     MsiViewClose( view );
4077     MsiCloseHandle( view );
4078
4079     /* query the table data */
4080     rec = 0;
4081     r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
4082     ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
4083     MsiCloseHandle( rec );
4084
4085     /* query the column data */
4086     rec = 0;
4087     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
4088     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4089     if (rec) MsiCloseHandle( rec );
4090
4091     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
4092     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4093     if (rec) MsiCloseHandle( rec );
4094
4095     MsiCloseHandle( hdb );
4096
4097     DeleteFile(msifile);
4098 }
4099
4100 static void test_alter(void)
4101 {
4102     MSICONDITION cond;
4103     MSIHANDLE hdb = 0;
4104     const char *query;
4105     UINT r;
4106
4107     hdb = create_db();
4108     ok( hdb, "failed to create db\n");
4109
4110     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4111     r = run_query(hdb, 0, query);
4112     ok(r == ERROR_SUCCESS, "failed to add table\n");
4113
4114     cond = MsiDatabaseIsTablePersistent(hdb, "T");
4115     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4116
4117     query = "ALTER TABLE `T` HOLD";
4118     r = run_query(hdb, 0, query);
4119     ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4120
4121     query = "ALTER TABLE `T` FREE";
4122     r = run_query(hdb, 0, query);
4123     ok(r == ERROR_SUCCESS, "failed to free table\n");
4124
4125     query = "ALTER TABLE `T` FREE";
4126     r = run_query(hdb, 0, query);
4127     ok(r == ERROR_SUCCESS, "failed to free table\n");
4128
4129     query = "ALTER TABLE `T` FREE";
4130     r = run_query(hdb, 0, query);
4131     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4132
4133     query = "ALTER TABLE `T` HOLD";
4134     r = run_query(hdb, 0, query);
4135     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4136
4137     /* table T is removed */
4138     query = "SELECT * FROM `T`";
4139     r = run_query(hdb, 0, query);
4140     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4141
4142     /* create the table again */
4143     query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4144     r = run_query(hdb, 0, query);
4145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4146
4147     /* up the ref count */
4148     query = "ALTER TABLE `U` HOLD";
4149     r = run_query(hdb, 0, query);
4150     ok(r == ERROR_SUCCESS, "failed to free table\n");
4151
4152     /* add column, no data type */
4153     query = "ALTER TABLE `U` ADD `C`";
4154     r = run_query(hdb, 0, query);
4155     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4156
4157     query = "ALTER TABLE `U` ADD `C` INTEGER";
4158     r = run_query(hdb, 0, query);
4159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4160
4161     /* add column C again */
4162     query = "ALTER TABLE `U` ADD `C` INTEGER";
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     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4167     r = run_query(hdb, 0, query);
4168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4169
4170     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4171     r = run_query(hdb, 0, query);
4172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4173
4174     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4175     r = run_query(hdb, 0, query);
4176     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4177
4178     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4179     r = run_query(hdb, 0, query);
4180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4181
4182     query = "SELECT * FROM `U` WHERE `D` = 8";
4183     r = run_query(hdb, 0, query);
4184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4185
4186     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
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 COLUMN `D` FREE";
4191     r = run_query(hdb, 0, query);
4192     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4193
4194     /* drop the ref count */
4195     query = "ALTER TABLE `U` FREE";
4196     r = run_query(hdb, 0, query);
4197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4198
4199     /* table is not empty */
4200     query = "SELECT * FROM `U`";
4201     r = run_query(hdb, 0, query);
4202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4203
4204     /* column D is removed */
4205     query = "SELECT * FROM `U` WHERE `D` = 8";
4206     r = run_query(hdb, 0, query);
4207     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4208
4209     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4210     r = run_query(hdb, 0, query);
4211     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4212
4213     /* add the column again */
4214     query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4215     r = run_query(hdb, 0, query);
4216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4217
4218     /* up the ref count */
4219     query = "ALTER TABLE `U` HOLD";
4220     r = run_query(hdb, 0, query);
4221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4222
4223     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4224     r = run_query(hdb, 0, query);
4225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4226
4227     query = "SELECT * FROM `U` WHERE `E` = 16";
4228     r = run_query(hdb, 0, query);
4229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4230
4231     /* drop the ref count */
4232     query = "ALTER TABLE `U` FREE";
4233     r = run_query(hdb, 0, query);
4234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4235
4236     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4237     r = run_query(hdb, 0, query);
4238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4239
4240     query = "SELECT * FROM `U` WHERE `E` = 20";
4241     r = run_query(hdb, 0, query);
4242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4243
4244     /* drop the ref count */
4245     query = "ALTER TABLE `U` FREE";
4246     r = run_query(hdb, 0, query);
4247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4248
4249     /* table still exists */
4250     query = "SELECT * FROM `U`";
4251     r = run_query(hdb, 0, query);
4252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4253
4254     /* col E is removed */
4255     query = "SELECT * FROM `U` WHERE `E` = 20";
4256     r = run_query(hdb, 0, query);
4257     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4258
4259     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4260     r = run_query(hdb, 0, query);
4261     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4262
4263     /* drop the ref count once more */
4264     query = "ALTER TABLE `U` FREE";
4265     r = run_query(hdb, 0, query);
4266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4267
4268     /* table still exists */
4269     query = "SELECT * FROM `U`";
4270     r = run_query(hdb, 0, query);
4271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4272
4273     MsiCloseHandle( hdb );
4274     DeleteFile(msifile);
4275 }
4276
4277 static void test_integers(void)
4278 {
4279     MSIHANDLE hdb = 0, view = 0, rec = 0;
4280     DWORD count, i;
4281     const char *query;
4282     UINT r;
4283
4284     /* just MsiOpenDatabase should not create a file */
4285     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4286     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4287
4288     /* create a table */
4289     query = "CREATE TABLE `integers` ( "
4290             "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4291             "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4292             "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4293             "PRIMARY KEY `one`)";
4294     r = MsiDatabaseOpenView(hdb, query, &view);
4295     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4296     r = MsiViewExecute(view, 0);
4297     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4298     r = MsiViewClose(view);
4299     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4300     r = MsiCloseHandle(view);
4301     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4302
4303     query = "SELECT * FROM `integers`";
4304     r = MsiDatabaseOpenView(hdb, query, &view);
4305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4306
4307     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4309     count = MsiRecordGetFieldCount(rec);
4310     ok(count == 8, "Expected 8, got %d\n", count);
4311     ok(check_record(rec, 1, "one"), "Expected one\n");
4312     ok(check_record(rec, 2, "two"), "Expected two\n");
4313     ok(check_record(rec, 3, "three"), "Expected three\n");
4314     ok(check_record(rec, 4, "four"), "Expected four\n");
4315     ok(check_record(rec, 5, "five"), "Expected five\n");
4316     ok(check_record(rec, 6, "six"), "Expected six\n");
4317     ok(check_record(rec, 7, "seven"), "Expected seven\n");
4318     ok(check_record(rec, 8, "eight"), "Expected eight\n");
4319     MsiCloseHandle(rec);
4320
4321     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4323     count = MsiRecordGetFieldCount(rec);
4324     ok(count == 8, "Expected 8, got %d\n", count);
4325     ok(check_record(rec, 1, "I2"), "Expected I2\n");
4326     ok(check_record(rec, 2, "I2"), "Expected I2\n");
4327     ok(check_record(rec, 3, "I2"), "Expected I2\n");
4328     ok(check_record(rec, 4, "I4"), "Expected I4\n");
4329     ok(check_record(rec, 5, "i2"), "Expected i2\n");
4330     ok(check_record(rec, 6, "i2"), "Expected i2\n");
4331     ok(check_record(rec, 7, "i2"), "Expected i2\n");
4332     ok(check_record(rec, 8, "i4"), "Expected i4\n");
4333     MsiCloseHandle(rec);
4334
4335     MsiViewClose(view);
4336     MsiCloseHandle(view);
4337
4338     /* insert values into it, NULL where NOT NULL is specified */
4339     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4340         "VALUES('', '', '', '', '', '', '', '')";
4341     r = MsiDatabaseOpenView(hdb, query, &view);
4342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4343     r = MsiViewExecute(view, 0);
4344     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4345
4346     MsiViewClose(view);
4347     MsiCloseHandle(view);
4348
4349     query = "SELECT * FROM `integers`";
4350     r = do_query(hdb, query, &rec);
4351     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4352
4353     r = MsiRecordGetFieldCount(rec);
4354     ok(r == -1, "record count wrong: %d\n", r);
4355
4356     MsiCloseHandle(rec);
4357
4358     /* insert legitimate values into it */
4359     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4360         "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4361     r = MsiDatabaseOpenView(hdb, query, &view);
4362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4363     r = MsiViewExecute(view, 0);
4364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4365
4366     query = "SELECT * FROM `integers`";
4367     r = do_query(hdb, query, &rec);
4368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4369
4370     r = MsiRecordGetFieldCount(rec);
4371     ok(r == 8, "record count wrong: %d\n", r);
4372
4373     i = MsiRecordGetInteger(rec, 1);
4374     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4375     i = MsiRecordGetInteger(rec, 3);
4376     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4377     i = MsiRecordGetInteger(rec, 2);
4378     ok(i == 2, "Expected 2, got %d\n", i);
4379     i = MsiRecordGetInteger(rec, 4);
4380     ok(i == 4, "Expected 4, got %d\n", i);
4381     i = MsiRecordGetInteger(rec, 5);
4382     ok(i == 5, "Expected 5, got %d\n", i);
4383     i = MsiRecordGetInteger(rec, 6);
4384     ok(i == 6, "Expected 6, got %d\n", i);
4385     i = MsiRecordGetInteger(rec, 7);
4386     ok(i == 7, "Expected 7, got %d\n", i);
4387     i = MsiRecordGetInteger(rec, 8);
4388     ok(i == 8, "Expected 8, got %d\n", i);
4389
4390     MsiCloseHandle(rec);
4391     MsiViewClose(view);
4392     MsiCloseHandle(view);
4393
4394     r = MsiDatabaseCommit(hdb);
4395     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4396
4397     r = MsiCloseHandle(hdb);
4398     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4399
4400     r = DeleteFile(msifile);
4401     ok(r == TRUE, "file didn't exist after commit\n");
4402 }
4403
4404 static void test_update(void)
4405 {
4406     MSIHANDLE hdb = 0, view = 0, rec = 0;
4407     CHAR result[MAX_PATH];
4408     const char *query;
4409     DWORD size;
4410     UINT r;
4411
4412     /* just MsiOpenDatabase should not create a file */
4413     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4414     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4415
4416     /* create the Control table */
4417     query = "CREATE TABLE `Control` ( "
4418         "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4419         "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4420         "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4421         "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4422     r = MsiDatabaseOpenView(hdb, query, &view);
4423     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4424     r = MsiViewExecute(view, 0);
4425     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4426     r = MsiViewClose(view);
4427     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4428     r = MsiCloseHandle(view);
4429     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4430
4431     /* add a control */
4432     query = "INSERT INTO `Control` ( "
4433         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4434         "`Property`, `Text`, `Control_Next`, `Help` )"
4435         "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4436     r = MsiDatabaseOpenView(hdb, query, &view);
4437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4438     r = MsiViewExecute(view, 0);
4439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4440     r = MsiViewClose(view);
4441     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4442     r = MsiCloseHandle(view);
4443     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4444
4445     /* add a second control */
4446     query = "INSERT INTO `Control` ( "
4447         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4448         "`Property`, `Text`, `Control_Next`, `Help` )"
4449         "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4450     r = MsiDatabaseOpenView(hdb, query, &view);
4451     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4452     r = MsiViewExecute(view, 0);
4453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4454     r = MsiViewClose(view);
4455     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4456     r = MsiCloseHandle(view);
4457     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4458
4459     /* add a third control */
4460     query = "INSERT INTO `Control` ( "
4461         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4462         "`Property`, `Text`, `Control_Next`, `Help` )"
4463         "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4464     r = MsiDatabaseOpenView(hdb, query, &view);
4465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4466     r = MsiViewExecute(view, 0);
4467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4468     r = MsiViewClose(view);
4469     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4470     r = MsiCloseHandle(view);
4471     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4472
4473     /* bad table */
4474     query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4475     r = MsiDatabaseOpenView(hdb, query, &view);
4476     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4477
4478     /* bad set column */
4479     query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4480     r = MsiDatabaseOpenView(hdb, query, &view);
4481     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4482
4483     /* bad where condition */
4484     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4485     r = MsiDatabaseOpenView(hdb, query, &view);
4486     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4487
4488     /* just the dialog_ specified */
4489     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4490     r = MsiDatabaseOpenView(hdb, query, &view);
4491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4492     r = MsiViewExecute(view, 0);
4493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4494     r = MsiViewClose(view);
4495     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4496     r = MsiCloseHandle(view);
4497     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4498
4499     /* check the modified text */
4500     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4501     r = MsiDatabaseOpenView(hdb, query, &view);
4502     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4503     r = MsiViewExecute(view, 0);
4504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4505
4506     r = MsiViewFetch(view, &rec);
4507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4508
4509     size = MAX_PATH;
4510     r = MsiRecordGetString(rec, 1, result, &size);
4511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4512     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4513
4514     MsiCloseHandle(rec);
4515
4516     r = MsiViewFetch(view, &rec);
4517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4518
4519     size = MAX_PATH;
4520     r = MsiRecordGetString(rec, 1, result, &size);
4521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4522     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4523
4524     MsiCloseHandle(rec);
4525
4526     r = MsiViewFetch(view, &rec);
4527     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4528
4529     r = MsiViewClose(view);
4530     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4531     r = MsiCloseHandle(view);
4532     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4533
4534     /* dialog_ and control specified */
4535     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4536     r = MsiDatabaseOpenView(hdb, query, &view);
4537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4538     r = MsiViewExecute(view, 0);
4539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4540     r = MsiViewClose(view);
4541     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4542     r = MsiCloseHandle(view);
4543     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4544
4545     /* check the modified text */
4546     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4547     r = MsiDatabaseOpenView(hdb, query, &view);
4548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4549     r = MsiViewExecute(view, 0);
4550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4551
4552     r = MsiViewFetch(view, &rec);
4553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4554
4555     size = MAX_PATH;
4556     r = MsiRecordGetString(rec, 1, result, &size);
4557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4558     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4559
4560     MsiCloseHandle(rec);
4561
4562     r = MsiViewFetch(view, &rec);
4563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4564
4565     size = MAX_PATH;
4566     r = MsiRecordGetString(rec, 1, result, &size);
4567     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4568     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4569
4570     MsiCloseHandle(rec);
4571
4572     r = MsiViewFetch(view, &rec);
4573     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4574
4575     r = MsiViewClose(view);
4576     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4577     r = MsiCloseHandle(view);
4578     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4579
4580     /* no where condition */
4581     query = "UPDATE `Control` SET `Text` = 'this is text'";
4582     r = MsiDatabaseOpenView(hdb, query, &view);
4583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4584     r = MsiViewExecute(view, 0);
4585     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4586     r = MsiViewClose(view);
4587     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4588     r = MsiCloseHandle(view);
4589     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4590
4591     /* check the modified text */
4592     query = "SELECT `Text` FROM `Control`";
4593     r = MsiDatabaseOpenView(hdb, query, &view);
4594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4595     r = MsiViewExecute(view, 0);
4596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4597
4598     r = MsiViewFetch(view, &rec);
4599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4600
4601     size = MAX_PATH;
4602     r = MsiRecordGetString(rec, 1, result, &size);
4603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4604     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4605
4606     MsiCloseHandle(rec);
4607
4608     r = MsiViewFetch(view, &rec);
4609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4610
4611     size = MAX_PATH;
4612     r = MsiRecordGetString(rec, 1, result, &size);
4613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4614     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4615
4616     MsiCloseHandle(rec);
4617
4618     r = MsiViewFetch(view, &rec);
4619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4620
4621     size = MAX_PATH;
4622     r = MsiRecordGetString(rec, 1, result, &size);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4625
4626     MsiCloseHandle(rec);
4627
4628     r = MsiViewFetch(view, &rec);
4629     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4630
4631     r = MsiViewClose(view);
4632     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4633     r = MsiCloseHandle(view);
4634     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4635
4636     query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4637         "`Orange` CHAR(72),  `Pear` INT PRIMARY KEY `Banana`)";
4638     r = run_query(hdb, 0, query);
4639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4640
4641     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4642         "VALUES('one', 'two', 3)";
4643     r = run_query(hdb, 0, query);
4644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4645
4646     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4647         "VALUES('three', 'four', 5)";
4648     r = run_query(hdb, 0, query);
4649     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4650
4651     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4652         "VALUES('six', 'two', 7)";
4653     r = run_query(hdb, 0, query);
4654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4655
4656     rec = MsiCreateRecord(2);
4657     MsiRecordSetInteger(rec, 1, 8);
4658     MsiRecordSetString(rec, 2, "two");
4659
4660     query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4661     r = run_query(hdb, rec, query);
4662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4663
4664     MsiCloseHandle(rec);
4665
4666     query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4667     r = MsiDatabaseOpenView(hdb, query, &view);
4668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4669     r = MsiViewExecute(view, 0);
4670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4671
4672     r = MsiViewFetch(view, &rec);
4673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4674
4675     r = MsiRecordGetInteger(rec, 1);
4676     ok(r == 8, "Expected 8, got %d\n", r);
4677
4678     MsiCloseHandle(rec);
4679
4680     r = MsiViewFetch(view, &rec);
4681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4682
4683     r = MsiRecordGetInteger(rec, 1);
4684     ok(r == 8, "Expected 8, got %d\n", r);
4685
4686     MsiCloseHandle(rec);
4687
4688     r = MsiViewFetch(view, &rec);
4689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4690
4691     r = MsiRecordGetInteger(rec, 1);
4692     ok(r == 5, "Expected 5, got %d\n", r);
4693
4694     MsiCloseHandle(rec);
4695
4696     r = MsiViewFetch(view, &rec);
4697     ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4698
4699     MsiViewClose(view);
4700     MsiCloseHandle(view);
4701
4702     r = MsiDatabaseCommit(hdb);
4703     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4704     r = MsiCloseHandle(hdb);
4705     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4706
4707     DeleteFile(msifile);
4708 }
4709
4710 static void test_special_tables(void)
4711 {
4712     const char *query;
4713     MSIHANDLE hdb = 0;
4714     UINT r;
4715
4716     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4717     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4718
4719     query = "CREATE TABLE `_Properties` ( "
4720         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4721     r = run_query(hdb, 0, query);
4722     ok(r == ERROR_SUCCESS, "failed to create table\n");
4723
4724     query = "CREATE TABLE `_Storages` ( "
4725         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4726     r = run_query(hdb, 0, query);
4727     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4728
4729     query = "CREATE TABLE `_Streams` ( "
4730         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4731     r = run_query(hdb, 0, query);
4732     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4733
4734     query = "CREATE TABLE `_Tables` ( "
4735         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4736     r = run_query(hdb, 0, query);
4737     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4738
4739     query = "CREATE TABLE `_Columns` ( "
4740         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4741     r = run_query(hdb, 0, query);
4742     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4743
4744     r = MsiCloseHandle(hdb);
4745     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4746 }
4747
4748 static void test_tables_order(void)
4749 {
4750     const char *query;
4751     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4752     UINT r;
4753     char buffer[100];
4754     DWORD sz;
4755
4756     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4757     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4758
4759     query = "CREATE TABLE `foo` ( "
4760         "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4761     r = run_query(hdb, 0, query);
4762     ok(r == ERROR_SUCCESS, "failed to create table\n");
4763
4764     query = "CREATE TABLE `bar` ( "
4765         "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4766     r = run_query(hdb, 0, query);
4767     ok(r == ERROR_SUCCESS, "failed to create table\n");
4768
4769     query = "CREATE TABLE `baz` ( "
4770         "`bar` INT NOT NULL, "
4771         "`baz` INT NOT NULL, "
4772         "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4773     r = run_query(hdb, 0, query);
4774     ok(r == ERROR_SUCCESS, "failed to create table\n");
4775
4776     /* The names of the tables in the _Tables table must
4777        be in the same order as these names are created in
4778        the strings table. */
4779     query = "SELECT * FROM `_Tables`";
4780     r = MsiDatabaseOpenView(hdb, query, &hview);
4781     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4782     r = MsiViewExecute(hview, 0);
4783     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4784
4785     r = MsiViewFetch(hview, &hrec);
4786     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4787     sz = sizeof(buffer);
4788     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4790     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4791     r = MsiCloseHandle(hrec);
4792     ok(r == ERROR_SUCCESS, "failed to close record\n");
4793
4794     r = MsiViewFetch(hview, &hrec);
4795     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4796     sz = sizeof(buffer);
4797     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4799     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4800     r = MsiCloseHandle(hrec);
4801     ok(r == ERROR_SUCCESS, "failed to close record\n");
4802
4803     r = MsiViewFetch(hview, &hrec);
4804     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4805     sz = sizeof(buffer);
4806     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4807     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4808     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4809     r = MsiCloseHandle(hrec);
4810     ok(r == ERROR_SUCCESS, "failed to close record\n");
4811
4812     r = MsiViewClose(hview);
4813     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4814     r = MsiCloseHandle(hview);
4815     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4816
4817     /* The names of the tables in the _Columns table must
4818        be in the same order as these names are created in
4819        the strings table. */
4820     query = "SELECT * FROM `_Columns`";
4821     r = MsiDatabaseOpenView(hdb, query, &hview);
4822     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4823     r = MsiViewExecute(hview, 0);
4824     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4825
4826     r = MsiViewFetch(hview, &hrec);
4827     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4828     sz = sizeof(buffer);
4829     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4831     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4832     sz = sizeof(buffer);
4833     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4835     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4836     r = MsiCloseHandle(hrec);
4837     ok(r == ERROR_SUCCESS, "failed to close record\n");
4838
4839     r = MsiViewFetch(hview, &hrec);
4840     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4841     sz = sizeof(buffer);
4842     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4844     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4845     sz = sizeof(buffer);
4846     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4848     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4849     r = MsiCloseHandle(hrec);
4850     ok(r == ERROR_SUCCESS, "failed to close record\n");
4851
4852     r = MsiViewFetch(hview, &hrec);
4853     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4854     sz = sizeof(buffer);
4855     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4857     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4858     sz = sizeof(buffer);
4859     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4861     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4862     r = MsiCloseHandle(hrec);
4863     ok(r == ERROR_SUCCESS, "failed to close record\n");
4864
4865     r = MsiViewFetch(hview, &hrec);
4866     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4867     sz = sizeof(buffer);
4868     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4870     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4871     sz = sizeof(buffer);
4872     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4874     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4875     r = MsiCloseHandle(hrec);
4876     ok(r == ERROR_SUCCESS, "failed to close record\n");
4877
4878     r = MsiViewFetch(hview, &hrec);
4879     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4880     sz = sizeof(buffer);
4881     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4883     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4884     sz = sizeof(buffer);
4885     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4887     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4888     r = MsiCloseHandle(hrec);
4889     ok(r == ERROR_SUCCESS, "failed to close record\n");
4890
4891     r = MsiViewClose(hview);
4892     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4893     r = MsiCloseHandle(hview);
4894     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4895
4896     r = MsiCloseHandle(hdb);
4897     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4898
4899     DeleteFile(msifile);
4900 }
4901
4902 static void test_rows_order(void)
4903 {
4904     const char *query;
4905     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4906     UINT r;
4907     char buffer[100];
4908     DWORD sz;
4909
4910     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4911     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4912
4913     query = "CREATE TABLE `foo` ( "
4914         "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4915     r = run_query(hdb, 0, query);
4916     ok(r == ERROR_SUCCESS, "failed to create table\n");
4917
4918     r = run_query(hdb, 0, "INSERT INTO `foo` "
4919             "( `bar` ) VALUES ( 'A' )");
4920     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4921
4922     r = run_query(hdb, 0, "INSERT INTO `foo` "
4923             "( `bar` ) VALUES ( 'B' )");
4924     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4925
4926     r = run_query(hdb, 0, "INSERT INTO `foo` "
4927             "( `bar` ) VALUES ( 'C' )");
4928     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4929
4930     r = run_query(hdb, 0, "INSERT INTO `foo` "
4931             "( `bar` ) VALUES ( 'D' )");
4932     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4933
4934     r = run_query(hdb, 0, "INSERT INTO `foo` "
4935             "( `bar` ) VALUES ( 'E' )");
4936     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4937
4938     r = run_query(hdb, 0, "INSERT INTO `foo` "
4939             "( `bar` ) VALUES ( 'F' )");
4940     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4941
4942     query = "CREATE TABLE `bar` ( "
4943         "`foo` LONGCHAR NOT NULL, "
4944         "`baz` LONGCHAR NOT NULL "
4945         "PRIMARY KEY `foo` )";
4946     r = run_query(hdb, 0, query);
4947     ok(r == ERROR_SUCCESS, "failed to create table\n");
4948
4949     r = run_query(hdb, 0, "INSERT INTO `bar` "
4950             "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4951     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4952
4953     r = run_query(hdb, 0, "INSERT INTO `bar` "
4954             "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4955     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4956
4957     r = run_query(hdb, 0, "INSERT INTO `bar` "
4958             "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4959     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4960
4961     r = run_query(hdb, 0, "INSERT INTO `bar` "
4962             "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4963     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4964
4965     /* The rows of the table must be ordered by the column values of
4966        each row. For strings, the column value is the string id
4967        in the string table.  */
4968
4969     query = "SELECT * FROM `bar`";
4970     r = MsiDatabaseOpenView(hdb, query, &hview);
4971     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4972     r = MsiViewExecute(hview, 0);
4973     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4974
4975     r = MsiViewFetch(hview, &hrec);
4976     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4977     sz = sizeof(buffer);
4978     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4979     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4980     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4981     sz = sizeof(buffer);
4982     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4984     ok(!lstrcmp(buffer, "B"), "Expected B, got %s\n", buffer);
4985     r = MsiCloseHandle(hrec);
4986     ok(r == ERROR_SUCCESS, "failed to close record\n");
4987
4988     r = MsiViewFetch(hview, &hrec);
4989     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4990     sz = sizeof(buffer);
4991     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4993     ok(!lstrcmp(buffer, "C"), "Expected E, got %s\n", buffer);
4994     sz = sizeof(buffer);
4995     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4996     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4997     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4998     r = MsiCloseHandle(hrec);
4999     ok(r == ERROR_SUCCESS, "failed to close record\n");
5000
5001     r = MsiViewFetch(hview, &hrec);
5002     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5003     sz = sizeof(buffer);
5004     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5006     ok(!lstrcmp(buffer, "D"), "Expected D, got %s\n", buffer);
5007     sz = sizeof(buffer);
5008     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5009     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5010     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
5011     r = MsiCloseHandle(hrec);
5012     ok(r == ERROR_SUCCESS, "failed to close record\n");
5013
5014     r = MsiViewFetch(hview, &hrec);
5015     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5016     sz = sizeof(buffer);
5017     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5019     ok(!lstrcmp(buffer, "F"), "Expected F, got %s\n", buffer);
5020     sz = sizeof(buffer);
5021     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5023     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
5024     r = MsiCloseHandle(hrec);
5025     ok(r == ERROR_SUCCESS, "failed to close record\n");
5026
5027     r = MsiViewClose(hview);
5028     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5029     r = MsiCloseHandle(hview);
5030     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5031
5032     r = MsiCloseHandle(hdb);
5033     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5034
5035     DeleteFile(msifile);
5036 }
5037
5038 static void test_collation(void)
5039 {
5040     static const WCHAR query1[] =
5041         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5042          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5043          '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
5044     static const WCHAR query2[] =
5045         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5046          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5047          '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
5048     static const WCHAR query3[] =
5049         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
5050          '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
5051            ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
5052            'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
5053     static const WCHAR query4[] =
5054         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
5055          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5056          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5057     static const WCHAR query5[] =
5058         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
5059          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5060          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5061     static const WCHAR query6[] =
5062         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
5063          ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
5064     static const WCHAR letter_C[] = {'C',0};
5065     static const WCHAR letter_D[] = {'D',0};
5066     static const WCHAR letter_a_ring[] = {'a',0x30a,0};
5067     static const WCHAR letter_a_with_ring[] = {0xe5,0};
5068     const char *query;
5069     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5070     UINT r;
5071     char buffer[100];
5072     WCHAR bufferW[100];
5073     DWORD sz;
5074
5075     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5076     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5077
5078     query = "CREATE TABLE `bar` ( "
5079         "`foo` LONGCHAR NOT NULL, "
5080         "`baz` LONGCHAR NOT NULL "
5081         "PRIMARY KEY `foo` )";
5082     r = run_query(hdb, 0, query);
5083     ok(r == ERROR_SUCCESS, "failed to create table\n");
5084
5085     r = run_query(hdb, 0, query);
5086     ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
5087
5088     r = run_query(hdb, 0, "INSERT INTO `bar` "
5089             "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
5090     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5091
5092     r = run_query(hdb, 0, "INSERT INTO `bar` "
5093             "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
5094     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5095
5096     r = run_queryW(hdb, 0, query1);
5097     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5098
5099     r = run_queryW(hdb, 0, query2);
5100     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5101
5102     r = run_queryW(hdb, 0, query3);
5103     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5104
5105     r = run_queryW(hdb, 0, query4);
5106     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5107
5108     r = run_queryW(hdb, 0, query5);
5109     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5110
5111     query = "SELECT * FROM `bar`";
5112     r = MsiDatabaseOpenView(hdb, query, &hview);
5113     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5114     r = MsiViewExecute(hview, 0);
5115     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5116
5117     r = MsiViewFetch(hview, &hrec);
5118     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5119     sz = sizeof(buffer);
5120     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5121     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5122     ok(!lstrcmp(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
5123     sz = sizeof(buffer);
5124     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5126     ok(!lstrcmp(buffer, "A"), "Expected A, got '%s'\n", buffer);
5127     MsiCloseHandle(hrec);
5128
5129     r = MsiViewFetch(hview, &hrec);
5130     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5131     sz = sizeof(buffer);
5132     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5134     ok(!lstrcmp(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
5135     sz = sizeof(buffer);
5136     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5138     ok(!lstrcmp(buffer, "B"), "Expected B, got '%s'\n", buffer);
5139     MsiCloseHandle(hrec);
5140
5141     r = MsiViewFetch(hview, &hrec);
5142     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5143     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5144     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5146     ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)),
5147        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
5148     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5149     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5151     ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
5152     MsiCloseHandle(hrec);
5153
5154     r = MsiViewFetch(hview, &hrec);
5155     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5156     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5157     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5159     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5160        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5161     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5162     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5164     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5165     MsiCloseHandle(hrec);
5166
5167     r = MsiViewClose(hview);
5168     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5169     r = MsiCloseHandle(hview);
5170     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5171
5172     r = MsiDatabaseOpenViewW(hdb, query6, &hview);
5173     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5174     r = MsiViewExecute(hview, 0);
5175     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5176
5177     r = MsiViewFetch(hview, &hrec);
5178     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5179     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5180     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5182     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5183        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5184     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5185     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5187     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5188     MsiCloseHandle(hrec);
5189
5190     r = MsiViewFetch(hview, &hrec);
5191     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
5192
5193     r = MsiViewClose(hview);
5194     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5195     r = MsiCloseHandle(hview);
5196     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5197
5198     r = MsiCloseHandle(hdb);
5199     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5200
5201     DeleteFile(msifile);
5202 }
5203
5204 static void test_select_markers(void)
5205 {
5206     MSIHANDLE hdb = 0, rec, view, res;
5207     LPCSTR query;
5208     UINT r;
5209     DWORD size;
5210     CHAR buf[MAX_PATH];
5211
5212     hdb = create_db();
5213     ok( hdb, "failed to create db\n");
5214
5215     r = run_query(hdb, 0,
5216             "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
5217     ok(r == S_OK, "cannot create table: %d\n", r);
5218
5219     r = run_query(hdb, 0, "INSERT INTO `Table` "
5220             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
5221     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5222
5223     r = run_query(hdb, 0, "INSERT INTO `Table` "
5224             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
5225     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5226
5227     r = run_query(hdb, 0, "INSERT INTO `Table` "
5228             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
5229     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5230
5231     r = run_query(hdb, 0, "INSERT INTO `Table` "
5232             "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
5233     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5234
5235     rec = MsiCreateRecord(2);
5236     MsiRecordSetString(rec, 1, "apple");
5237     MsiRecordSetString(rec, 2, "two");
5238
5239     query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
5240     r = MsiDatabaseOpenView(hdb, query, &view);
5241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5242
5243     r = MsiViewExecute(view, rec);
5244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5245
5246     r = MsiViewFetch(view, &res);
5247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5248
5249     size = MAX_PATH;
5250     r = MsiRecordGetString(res, 1, buf, &size);
5251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5252     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5253
5254     size = MAX_PATH;
5255     r = MsiRecordGetString(res, 2, buf, &size);
5256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5257     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5258
5259     r = MsiRecordGetInteger(res, 3);
5260     ok(r == 1, "Expected 1, got %d\n", r);
5261
5262     MsiCloseHandle(res);
5263
5264     r = MsiViewFetch(view, &res);
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5266
5267     size = MAX_PATH;
5268     r = MsiRecordGetString(res, 1, buf, &size);
5269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5270     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5271
5272     size = MAX_PATH;
5273     r = MsiRecordGetString(res, 2, buf, &size);
5274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5275     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5276
5277     r = MsiRecordGetInteger(res, 3);
5278     ok(r == 2, "Expected 2, got %d\n", r);
5279
5280     MsiCloseHandle(res);
5281
5282     r = MsiViewFetch(view, &res);
5283     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5284
5285     MsiCloseHandle(rec);
5286     MsiViewClose(view);
5287     MsiCloseHandle(view);
5288
5289     rec = MsiCreateRecord(2);
5290     MsiRecordSetString(rec, 1, "one");
5291     MsiRecordSetInteger(rec, 2, 1);
5292
5293     query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5294     r = MsiDatabaseOpenView(hdb, query, &view);
5295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5296     r = MsiViewExecute(view, rec);
5297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5298
5299     r = MsiViewFetch(view, &res);
5300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5301
5302     size = MAX_PATH;
5303     r = MsiRecordGetString(res, 1, buf, &size);
5304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5305     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5306
5307     size = MAX_PATH;
5308     r = MsiRecordGetString(res, 2, buf, &size);
5309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5310     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5311
5312     r = MsiRecordGetInteger(res, 3);
5313     ok(r == 2, "Expected 2, got %d\n", r);
5314
5315     MsiCloseHandle(res);
5316
5317     r = MsiViewFetch(view, &res);
5318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5319
5320     size = MAX_PATH;
5321     r = MsiRecordGetString(res, 1, buf, &size);
5322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5323     ok(!lstrcmp(buf, "banana"), "Expected banana, got %s\n", buf);
5324
5325     size = MAX_PATH;
5326     r = MsiRecordGetString(res, 2, buf, &size);
5327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5328     ok(!lstrcmp(buf, "three"), "Expected three, got %s\n", buf);
5329
5330     r = MsiRecordGetInteger(res, 3);
5331     ok(r == 3, "Expected 3, got %d\n", r);
5332
5333     MsiCloseHandle(res);
5334
5335     r = MsiViewFetch(view, &res);
5336     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5337
5338     MsiCloseHandle(rec);
5339     MsiViewClose(view);
5340     MsiCloseHandle(view);
5341     MsiCloseHandle(hdb);
5342     DeleteFile(msifile);
5343 }
5344
5345 static void test_viewmodify_update(void)
5346 {
5347     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5348     UINT i, test_max, offset, count;
5349     const char *query;
5350     UINT r;
5351
5352     DeleteFile(msifile);
5353
5354     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5355     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5356
5357     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5358     r = run_query( hdb, 0, query );
5359     ok(r == ERROR_SUCCESS, "query failed\n");
5360
5361     query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5362     r = run_query( hdb, 0, query );
5363     ok(r == ERROR_SUCCESS, "query failed\n");
5364
5365     query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5366     r = run_query( hdb, 0, query );
5367     ok(r == ERROR_SUCCESS, "query failed\n");
5368
5369     query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5370     r = run_query( hdb, 0, query );
5371     ok(r == ERROR_SUCCESS, "query failed\n");
5372
5373     query = "SELECT `B` FROM `table`";
5374     r = MsiDatabaseOpenView(hdb, query, &hview);
5375     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5376     r = MsiViewExecute(hview, 0);
5377     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5378     r = MsiViewFetch(hview, &hrec);
5379     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5380
5381     r = MsiRecordSetInteger(hrec, 1, 0);
5382     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5383
5384     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5385     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5386
5387     r = MsiCloseHandle(hrec);
5388     ok(r == ERROR_SUCCESS, "failed to close record\n");
5389
5390     r = MsiViewClose(hview);
5391     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5392     r = MsiCloseHandle(hview);
5393     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5394
5395     query = "SELECT * FROM `table`";
5396     r = MsiDatabaseOpenView(hdb, query, &hview);
5397     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5398     r = MsiViewExecute(hview, 0);
5399     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5400     r = MsiViewFetch(hview, &hrec);
5401     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5402
5403     r = MsiRecordGetInteger(hrec, 1);
5404     ok(r == 1, "Expected 1, got %d\n", r);
5405     r = MsiRecordGetInteger(hrec, 2);
5406     ok(r == 0, "Expected 0, got %d\n", r);
5407
5408     r = MsiCloseHandle(hrec);
5409     ok(r == ERROR_SUCCESS, "failed to close record\n");
5410
5411     r = MsiViewFetch(hview, &hrec);
5412     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5413
5414     r = MsiRecordGetInteger(hrec, 1);
5415     ok(r == 3, "Expected 3, got %d\n", r);
5416     r = MsiRecordGetInteger(hrec, 2);
5417     ok(r == 4, "Expected 4, got %d\n", r);
5418
5419     r = MsiCloseHandle(hrec);
5420     ok(r == ERROR_SUCCESS, "failed to close record\n");
5421
5422     r = MsiViewFetch(hview, &hrec);
5423     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5424
5425     r = MsiRecordGetInteger(hrec, 1);
5426     ok(r == 5, "Expected 5, got %d\n", r);
5427     r = MsiRecordGetInteger(hrec, 2);
5428     ok(r == 6, "Expected 6, got %d\n", r);
5429
5430     r = MsiCloseHandle(hrec);
5431     ok(r == ERROR_SUCCESS, "failed to close record\n");
5432
5433     r = MsiViewFetch(hview, &hrec);
5434     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5435
5436     r = MsiViewClose(hview);
5437     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5438     r = MsiCloseHandle(hview);
5439     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5440
5441     /* loop through all elements */
5442     query = "SELECT `B` FROM `table`";
5443     r = MsiDatabaseOpenView(hdb, query, &hview);
5444     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5445     r = MsiViewExecute(hview, 0);
5446     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5447
5448     while (TRUE)
5449     {
5450         r = MsiViewFetch(hview, &hrec);
5451         if (r != ERROR_SUCCESS)
5452             break;
5453
5454         r = MsiRecordSetInteger(hrec, 1, 0);
5455         ok(r == ERROR_SUCCESS, "failed to set integer\n");
5456
5457         r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5458         ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5459
5460         r = MsiCloseHandle(hrec);
5461         ok(r == ERROR_SUCCESS, "failed to close record\n");
5462     }
5463
5464     r = MsiViewClose(hview);
5465     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5466     r = MsiCloseHandle(hview);
5467     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5468
5469     query = "SELECT * FROM `table`";
5470     r = MsiDatabaseOpenView(hdb, query, &hview);
5471     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5472     r = MsiViewExecute(hview, 0);
5473     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5474     r = MsiViewFetch(hview, &hrec);
5475     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5476
5477     r = MsiRecordGetInteger(hrec, 1);
5478     ok(r == 1, "Expected 1, got %d\n", r);
5479     r = MsiRecordGetInteger(hrec, 2);
5480     ok(r == 0, "Expected 0, got %d\n", r);
5481
5482     r = MsiCloseHandle(hrec);
5483     ok(r == ERROR_SUCCESS, "failed to close record\n");
5484
5485     r = MsiViewFetch(hview, &hrec);
5486     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5487
5488     r = MsiRecordGetInteger(hrec, 1);
5489     ok(r == 3, "Expected 3, got %d\n", r);
5490     r = MsiRecordGetInteger(hrec, 2);
5491     ok(r == 0, "Expected 0, got %d\n", r);
5492
5493     r = MsiCloseHandle(hrec);
5494     ok(r == ERROR_SUCCESS, "failed to close record\n");
5495
5496     r = MsiViewFetch(hview, &hrec);
5497     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5498
5499     r = MsiRecordGetInteger(hrec, 1);
5500     ok(r == 5, "Expected 5, got %d\n", r);
5501     r = MsiRecordGetInteger(hrec, 2);
5502     ok(r == 0, "Expected 0, got %d\n", r);
5503
5504     r = MsiCloseHandle(hrec);
5505     ok(r == ERROR_SUCCESS, "failed to close record\n");
5506
5507     r = MsiViewFetch(hview, &hrec);
5508     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5509
5510     r = MsiViewClose(hview);
5511     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5512     r = MsiCloseHandle(hview);
5513     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5514
5515     query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5516     r = run_query( hdb, 0, query );
5517     ok(r == ERROR_SUCCESS, "query failed\n");
5518
5519     query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5520     r = MsiDatabaseOpenView( hdb, query, &hview );
5521     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5522
5523     test_max = 100;
5524     offset = 1234;
5525     for(i = 0; i < test_max; i++)
5526     {
5527
5528         hrec = MsiCreateRecord( 2 );
5529         MsiRecordSetInteger( hrec, 1, test_max - i );
5530         MsiRecordSetInteger( hrec, 2, i );
5531
5532         r = MsiViewExecute( hview, hrec );
5533         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5534
5535         r = MsiCloseHandle( hrec );
5536         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5537     }
5538
5539     r = MsiViewClose( hview );
5540     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5541     r = MsiCloseHandle( hview );
5542     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5543
5544     /* Update. */
5545     query = "SELECT * FROM `table2` ORDER BY `B`";
5546     r = MsiDatabaseOpenView( hdb, query, &hview);
5547     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5548     r = MsiViewExecute( hview, 0 );
5549     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5550
5551     count = 0;
5552     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5553     {
5554         UINT b = MsiRecordGetInteger( hrec, 2 );
5555
5556         r = MsiRecordSetInteger( hrec, 2, b + offset);
5557         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5558
5559         r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5560         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5561
5562         r = MsiCloseHandle(hrec);
5563         ok(r == ERROR_SUCCESS, "failed to close record\n");
5564         count++;
5565     }
5566     ok(count == test_max, "Got count %d\n", count);
5567
5568     r = MsiViewClose(hview);
5569     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5570     r = MsiCloseHandle(hview);
5571     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5572
5573     /* Recheck. */
5574     query = "SELECT * FROM `table2` ORDER BY `B`";
5575     r = MsiDatabaseOpenView( hdb, query, &hview);
5576     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5577     r = MsiViewExecute( hview, 0 );
5578     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5579
5580     count = 0;
5581     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5582     {
5583         UINT a = MsiRecordGetInteger( hrec, 1 );
5584         UINT b = MsiRecordGetInteger( hrec, 2 );
5585         ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5586             a, b, test_max - a + offset, b);
5587
5588         r = MsiCloseHandle(hrec);
5589         ok(r == ERROR_SUCCESS, "failed to close record\n");
5590         count++;
5591     }
5592     ok(count == test_max, "Got count %d\n", count);
5593
5594     r = MsiViewClose(hview);
5595     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5596     r = MsiCloseHandle(hview);
5597     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5598
5599     r = MsiCloseHandle( hdb );
5600     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5601 }
5602
5603 static void test_viewmodify_assign(void)
5604 {
5605     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5606     const char *query;
5607     UINT r;
5608
5609     /* setup database */
5610     DeleteFile(msifile);
5611
5612     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5613     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5614
5615     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5616     r = run_query( hdb, 0, query );
5617     ok(r == ERROR_SUCCESS, "query failed\n");
5618
5619     /* assign to view, new primary key */
5620     query = "SELECT * FROM `table`";
5621     r = MsiDatabaseOpenView(hdb, query, &hview);
5622     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5623     r = MsiViewExecute(hview, 0);
5624     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5625
5626     hrec = MsiCreateRecord(2);
5627     ok(hrec != 0, "MsiCreateRecord failed\n");
5628
5629     r = MsiRecordSetInteger(hrec, 1, 1);
5630     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5631     r = MsiRecordSetInteger(hrec, 2, 2);
5632     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5633
5634     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5635     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5636
5637     r = MsiCloseHandle(hrec);
5638     ok(r == ERROR_SUCCESS, "failed to close record\n");
5639
5640     r = MsiViewClose(hview);
5641     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5642     r = MsiCloseHandle(hview);
5643     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5644
5645     query = "SELECT * FROM `table`";
5646     r = MsiDatabaseOpenView(hdb, query, &hview);
5647     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5648     r = MsiViewExecute(hview, 0);
5649     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5650     r = MsiViewFetch(hview, &hrec);
5651     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5652
5653     r = MsiRecordGetInteger(hrec, 1);
5654     ok(r == 1, "Expected 1, got %d\n", r);
5655     r = MsiRecordGetInteger(hrec, 2);
5656     ok(r == 2, "Expected 2, got %d\n", r);
5657
5658     r = MsiCloseHandle(hrec);
5659     ok(r == ERROR_SUCCESS, "failed to close record\n");
5660
5661     r = MsiViewFetch(hview, &hrec);
5662     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
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     /* assign to view, primary key matches */
5670     query = "SELECT * FROM `table`";
5671     r = MsiDatabaseOpenView(hdb, query, &hview);
5672     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5673     r = MsiViewExecute(hview, 0);
5674     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5675
5676     hrec = MsiCreateRecord(2);
5677     ok(hrec != 0, "MsiCreateRecord failed\n");
5678
5679     r = MsiRecordSetInteger(hrec, 1, 1);
5680     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5681     r = MsiRecordSetInteger(hrec, 2, 4);
5682     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5683
5684     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5685     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5686
5687     r = MsiCloseHandle(hrec);
5688     ok(r == ERROR_SUCCESS, "failed to close record\n");
5689
5690     r = MsiViewClose(hview);
5691     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5692     r = MsiCloseHandle(hview);
5693     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5694
5695     query = "SELECT * FROM `table`";
5696     r = MsiDatabaseOpenView(hdb, query, &hview);
5697     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5698     r = MsiViewExecute(hview, 0);
5699     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5700     r = MsiViewFetch(hview, &hrec);
5701     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5702
5703     r = MsiRecordGetInteger(hrec, 1);
5704     ok(r == 1, "Expected 1, got %d\n", r);
5705     r = MsiRecordGetInteger(hrec, 2);
5706     ok(r == 4, "Expected 4, got %d\n", r);
5707
5708     r = MsiCloseHandle(hrec);
5709     ok(r == ERROR_SUCCESS, "failed to close record\n");
5710
5711     r = MsiViewFetch(hview, &hrec);
5712     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
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     /* close database */
5720     r = MsiCloseHandle( hdb );
5721     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5722 }
5723
5724 static const WCHAR data10[] = { /* MOO */
5725     0x8001, 0x000b,
5726 };
5727 static const WCHAR data11[] = { /* AAR */
5728     0x8002, 0x8005,
5729     0x000c, 0x000f,
5730 };
5731 static const char data12[] = /* _StringData */
5732     "MOOABAARCDonetwofourfive";
5733 static const WCHAR data13[] = { /* _StringPool */
5734 /*  len, refs */
5735     0,   0,    /* string 0 ''     */
5736     0,   0,    /* string 1 ''     */
5737     0,   0,    /* string 2 ''     */
5738     0,   0,    /* string 3 ''     */
5739     0,   0,    /* string 4 ''     */
5740     3,   3,    /* string 5 'MOO'  */
5741     1,   1,    /* string 6 'A'    */
5742     1,   1,    /* string 7 'B'    */
5743     3,   3,    /* string 8 'AAR'  */
5744     1,   1,    /* string 9 'C'    */
5745     1,   1,    /* string a 'D'    */
5746     3,   1,    /* string b 'one'  */
5747     3,   1,    /* string c 'two'  */
5748     0,   0,    /* string d ''     */
5749     4,   1,    /* string e 'four' */
5750     4,   1,    /* string f 'five' */
5751 };
5752
5753 static void test_stringtable(void)
5754 {
5755     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5756     IStorage *stg = NULL;
5757     IStream *stm;
5758     WCHAR name[0x20];
5759     HRESULT hr;
5760     const char *query;
5761     char buffer[MAX_PATH];
5762     WCHAR data[MAX_PATH];
5763     DWORD sz, read;
5764     UINT r;
5765
5766     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5767     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5768     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5769     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5770     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5771
5772     DeleteFile(msifile);
5773
5774     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5776
5777     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5778     r = run_query(hdb, 0, query);
5779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5780
5781     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5782     r = run_query(hdb, 0, query);
5783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5784
5785     /* insert persistent row */
5786     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5787     r = run_query(hdb, 0, query);
5788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5789
5790     /* insert persistent row */
5791     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5792     r = run_query(hdb, 0, query);
5793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5794
5795     /* open a view */
5796     query = "SELECT * FROM `MOO`";
5797     r = MsiDatabaseOpenView(hdb, query, &hview);
5798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5799     r = MsiViewExecute(hview, 0);
5800     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5801
5802     hrec = MsiCreateRecord(2);
5803
5804     r = MsiRecordSetInteger(hrec, 1, 3);
5805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5806     r = MsiRecordSetString(hrec, 2, "three");
5807     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5808
5809     /* insert a nonpersistent row */
5810     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5811     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5812
5813     r = MsiCloseHandle(hrec);
5814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5815     r = MsiViewClose(hview);
5816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5817     r = MsiCloseHandle(hview);
5818     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5819
5820     /* insert persistent row */
5821     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5822     r = run_query(hdb, 0, query);
5823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5824
5825     /* insert persistent row */
5826     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5827     r = run_query(hdb, 0, query);
5828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5829
5830     r = MsiDatabaseCommit(hdb);
5831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5832
5833     r = MsiCloseHandle(hdb);
5834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5835
5836     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
5837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5838
5839     query = "SELECT * FROM `MOO`";
5840     r = MsiDatabaseOpenView(hdb, query, &hview);
5841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5842
5843     r = MsiViewExecute(hview, 0);
5844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5845
5846     r = MsiViewFetch(hview, &hrec);
5847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5848
5849     r = MsiRecordGetFieldCount(hrec);
5850     ok(r == 2, "Expected 2, got %d\n", r);
5851
5852     r = MsiRecordGetInteger(hrec, 1);
5853     ok(r == 1, "Expected 1, got %d\n", r);
5854
5855     sz = sizeof(buffer);
5856     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5858     ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
5859
5860     r = MsiCloseHandle(hrec);
5861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5862
5863     r = MsiViewFetch(hview, &hrec);
5864     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5865
5866     r = MsiViewClose(hview);
5867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5868     r = MsiCloseHandle(hview);
5869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5870     r = MsiCloseHandle(hrec);
5871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5872
5873     query = "SELECT * FROM `AAR`";
5874     r = MsiDatabaseOpenView(hdb, query, &hview);
5875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5876
5877     r = MsiViewExecute(hview, 0);
5878     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5879
5880     r = MsiViewFetch(hview, &hrec);
5881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5882
5883     r = MsiRecordGetFieldCount(hrec);
5884     ok(r == 2, "Expected 2, got %d\n", r);
5885
5886     r = MsiRecordGetInteger(hrec, 1);
5887     ok(r == 2, "Expected 2, got %d\n", r);
5888
5889     sz = sizeof(buffer);
5890     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5892     ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
5893
5894     r = MsiCloseHandle(hrec);
5895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5896
5897     r = MsiViewFetch(hview, &hrec);
5898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5899
5900     r = MsiRecordGetFieldCount(hrec);
5901     ok(r == 2, "Expected 2, got %d\n", r);
5902
5903     r = MsiRecordGetInteger(hrec, 1);
5904     ok(r == 5, "Expected 5, got %d\n", r);
5905
5906     sz = sizeof(buffer);
5907     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5909     ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
5910
5911     r = MsiCloseHandle(hrec);
5912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5913
5914     r = MsiViewFetch(hview, &hrec);
5915     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5916
5917     r = MsiViewClose(hview);
5918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5919     r = MsiCloseHandle(hview);
5920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5921     r = MsiCloseHandle(hrec);
5922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5923     r = MsiCloseHandle(hdb);
5924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5925
5926     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5927     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5928     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5929     ok(stg != NULL, "Expected non-NULL storage\n");
5930
5931     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5932     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5933     ok(stm != NULL, "Expected non-NULL stream\n");
5934
5935     hr = IStream_Read(stm, data, MAX_PATH, &read);
5936     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5937     ok(read == 4, "Expected 4, got %d\n", read);
5938     todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5939
5940     hr = IStream_Release(stm);
5941     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5942
5943     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5944     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5945     ok(stm != NULL, "Expected non-NULL stream\n");
5946
5947     hr = IStream_Read(stm, data, MAX_PATH, &read);
5948     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5949     ok(read == 8, "Expected 8, got %d\n", read);
5950     todo_wine
5951     {
5952         ok(!memcmp(data, data11, read), "Unexpected data\n");
5953     }
5954
5955     hr = IStream_Release(stm);
5956     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5957
5958     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5959     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5960     ok(stm != NULL, "Expected non-NULL stream\n");
5961
5962     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5963     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5964     ok(read == 24, "Expected 24, got %d\n", read);
5965     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5966
5967     hr = IStream_Release(stm);
5968     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5969
5970     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5971     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5972     ok(stm != NULL, "Expected non-NULL stream\n");
5973
5974     hr = IStream_Read(stm, data, MAX_PATH, &read);
5975     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5976     todo_wine
5977     {
5978         ok(read == 64, "Expected 64, got %d\n", read);
5979         ok(!memcmp(data, data13, read), "Unexpected data\n");
5980     }
5981
5982     hr = IStream_Release(stm);
5983     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5984
5985     hr = IStorage_Release(stg);
5986     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5987
5988     DeleteFileA(msifile);
5989 }
5990
5991 static void test_viewmodify_delete(void)
5992 {
5993     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5994     UINT r;
5995     const char *query;
5996     char buffer[0x100];
5997     DWORD sz;
5998
5999     DeleteFile(msifile);
6000
6001     /* just MsiOpenDatabase should not create a file */
6002     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6004
6005     query = "CREATE TABLE `phone` ( "
6006             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
6007             "PRIMARY KEY `id`)";
6008     r = run_query(hdb, 0, query);
6009     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6010
6011     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6012         "VALUES('1', 'Alan', '5030581')";
6013     r = run_query(hdb, 0, query);
6014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6015
6016     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6017         "VALUES('2', 'Barry', '928440')";
6018     r = run_query(hdb, 0, query);
6019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6020
6021     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6022         "VALUES('3', 'Cindy', '2937550')";
6023     r = run_query(hdb, 0, query);
6024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6025
6026     query = "SELECT * FROM `phone` WHERE `id` <= 2";
6027     r = MsiDatabaseOpenView(hdb, query, &hview);
6028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6029     r = MsiViewExecute(hview, 0);
6030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6031     r = MsiViewFetch(hview, &hrec);
6032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6033
6034     /* delete 1 */
6035     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6037
6038     r = MsiCloseHandle(hrec);
6039     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6040     r = MsiViewFetch(hview, &hrec);
6041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6042
6043     /* delete 2 */
6044     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6046
6047     r = MsiCloseHandle(hrec);
6048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6049     r = MsiViewClose(hview);
6050     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6051     r = MsiCloseHandle(hview);
6052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6053
6054     query = "SELECT * FROM `phone`";
6055     r = MsiDatabaseOpenView(hdb, query, &hview);
6056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6057     r = MsiViewExecute(hview, 0);
6058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6059     r = MsiViewFetch(hview, &hrec);
6060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6061
6062     r = MsiRecordGetInteger(hrec, 1);
6063     ok(r == 3, "Expected 3, got %d\n", r);
6064
6065     sz = sizeof(buffer);
6066     r = MsiRecordGetString(hrec, 2, buffer, &sz);
6067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6068     ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
6069
6070     sz = sizeof(buffer);
6071     r = MsiRecordGetString(hrec, 3, buffer, &sz);
6072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6073     ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
6074
6075     r = MsiCloseHandle(hrec);
6076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6077
6078     r = MsiViewFetch(hview, &hrec);
6079     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6080
6081     r = MsiViewClose(hview);
6082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6083     r = MsiCloseHandle(hview);
6084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6085     r = MsiCloseHandle(hdb);
6086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6087 }
6088
6089 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
6090 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
6091 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
6092
6093 static const WCHAR data14[] = { /* _StringPool */
6094 /*  len, refs */
6095     0,   0,    /* string 0 ''    */
6096 };
6097
6098 static const struct {
6099     LPCWSTR name;
6100     const void *data;
6101     DWORD size;
6102 } database_table_data[] =
6103 {
6104     {_Tables, NULL, 0},
6105     {_StringData, NULL, 0},
6106     {_StringPool, data14, sizeof data14},
6107 };
6108
6109 static void enum_stream_names(IStorage *stg)
6110 {
6111     IEnumSTATSTG *stgenum = NULL;
6112     IStream *stm;
6113     HRESULT hr;
6114     STATSTG stat;
6115     ULONG n, count;
6116     BYTE data[MAX_PATH];
6117     BYTE check[MAX_PATH];
6118     DWORD sz;
6119
6120     memset(check, 'a', MAX_PATH);
6121
6122     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
6123     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6124
6125     n = 0;
6126     while(TRUE)
6127     {
6128         count = 0;
6129         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
6130         if(FAILED(hr) || !count)
6131             break;
6132
6133         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
6134            "Expected table %d name to match\n", n);
6135
6136         stm = NULL;
6137         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
6138                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6139         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6140         ok(stm != NULL, "Expected non-NULL stream\n");
6141
6142         CoTaskMemFree(stat.pwcsName);
6143
6144         sz = MAX_PATH;
6145         memset(data, 'a', MAX_PATH);
6146         hr = IStream_Read(stm, data, sz, &count);
6147         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6148
6149         ok(count == database_table_data[n].size,
6150            "Expected %d, got %d\n", database_table_data[n].size, count);
6151
6152         if (!database_table_data[n].size)
6153             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
6154         else
6155             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
6156                "Expected table %d data to match\n", n);
6157
6158         IStream_Release(stm);
6159         n++;
6160     }
6161
6162     ok(n == 3, "Expected 3, got %d\n", n);
6163
6164     IEnumSTATSTG_Release(stgenum);
6165 }
6166
6167 static void test_defaultdatabase(void)
6168 {
6169     UINT r;
6170     HRESULT hr;
6171     MSIHANDLE hdb;
6172     IStorage *stg = NULL;
6173
6174     DeleteFile(msifile);
6175
6176     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6178
6179     r = MsiDatabaseCommit(hdb);
6180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6181
6182     MsiCloseHandle(hdb);
6183
6184     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6185     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6186     ok(stg != NULL, "Expected non-NULL stg\n");
6187
6188     enum_stream_names(stg);
6189
6190     IStorage_Release(stg);
6191     DeleteFileA(msifile);
6192 }
6193
6194 static void test_order(void)
6195 {
6196     MSIHANDLE hdb, hview, hrec;
6197     CHAR buffer[MAX_PATH];
6198     LPCSTR query;
6199     UINT r, sz;
6200     int val;
6201
6202     hdb = create_db();
6203     ok(hdb, "failed to create db\n");
6204
6205     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6206     r = run_query(hdb, 0, query);
6207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6208
6209     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6210     r = run_query(hdb, 0, query);
6211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6212
6213     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6214     r = run_query(hdb, 0, query);
6215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6216
6217     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6218     r = run_query(hdb, 0, query);
6219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6220
6221     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6222     r = run_query(hdb, 0, query);
6223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6224
6225     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6226     r = run_query(hdb, 0, query);
6227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6228
6229     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6230     r = run_query(hdb, 0, query);
6231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6232
6233     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6234     r = run_query(hdb, 0, query);
6235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6236
6237     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6238     r = run_query(hdb, 0, query);
6239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6240
6241     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6242     r = MsiDatabaseOpenView(hdb, query, &hview);
6243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6244     r = MsiViewExecute(hview, 0);
6245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6246
6247     r = MsiViewFetch(hview, &hrec);
6248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6249
6250     val = MsiRecordGetInteger(hrec, 1);
6251     ok(val == 3, "Expected 3, got %d\n", val);
6252
6253     val = MsiRecordGetInteger(hrec, 2);
6254     ok(val == 4, "Expected 3, got %d\n", val);
6255
6256     MsiCloseHandle(hrec);
6257
6258     r = MsiViewFetch(hview, &hrec);
6259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6260
6261     val = MsiRecordGetInteger(hrec, 1);
6262     ok(val == 5, "Expected 5, got %d\n", val);
6263
6264     val = MsiRecordGetInteger(hrec, 2);
6265     ok(val == 6, "Expected 6, got %d\n", val);
6266
6267     MsiCloseHandle(hrec);
6268
6269     r = MsiViewFetch(hview, &hrec);
6270     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6271
6272     val = MsiRecordGetInteger(hrec, 1);
6273     ok(val == 1, "Expected 1, got %d\n", val);
6274
6275     val = MsiRecordGetInteger(hrec, 2);
6276     ok(val == 2, "Expected 2, got %d\n", val);
6277
6278     MsiCloseHandle(hrec);
6279
6280     r = MsiViewFetch(hview, &hrec);
6281     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6282
6283     MsiViewClose(hview);
6284     MsiCloseHandle(hview);
6285
6286     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6287     r = MsiDatabaseOpenView(hdb, query, &hview);
6288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6289     r = MsiViewExecute(hview, 0);
6290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6291
6292     r = MsiViewFetch(hview, &hrec);
6293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6294
6295     val = MsiRecordGetInteger(hrec, 1);
6296     ok(val == 1, "Expected 1, got %d\n", val);
6297
6298     val = MsiRecordGetInteger(hrec, 2);
6299     ok(val == 12, "Expected 12, got %d\n", val);
6300
6301     MsiCloseHandle(hrec);
6302
6303     r = MsiViewFetch(hview, &hrec);
6304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6305
6306     val = MsiRecordGetInteger(hrec, 1);
6307     ok(val == 3, "Expected 3, got %d\n", val);
6308
6309     val = MsiRecordGetInteger(hrec, 2);
6310     ok(val == 12, "Expected 12, got %d\n", val);
6311
6312     MsiCloseHandle(hrec);
6313
6314     r = MsiViewFetch(hview, &hrec);
6315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6316
6317     val = MsiRecordGetInteger(hrec, 1);
6318     ok(val == 5, "Expected 5, got %d\n", val);
6319
6320     val = MsiRecordGetInteger(hrec, 2);
6321     ok(val == 12, "Expected 12, got %d\n", val);
6322
6323     MsiCloseHandle(hrec);
6324
6325     r = MsiViewFetch(hview, &hrec);
6326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6327
6328     val = MsiRecordGetInteger(hrec, 1);
6329     ok(val == 1, "Expected 1, got %d\n", val);
6330
6331     val = MsiRecordGetInteger(hrec, 2);
6332     ok(val == 14, "Expected 14, got %d\n", val);
6333
6334     MsiCloseHandle(hrec);
6335
6336     r = MsiViewFetch(hview, &hrec);
6337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6338
6339     val = MsiRecordGetInteger(hrec, 1);
6340     ok(val == 3, "Expected 3, got %d\n", val);
6341
6342     val = MsiRecordGetInteger(hrec, 2);
6343     ok(val == 14, "Expected 14, got %d\n", val);
6344
6345     MsiCloseHandle(hrec);
6346
6347     r = MsiViewFetch(hview, &hrec);
6348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6349
6350     val = MsiRecordGetInteger(hrec, 1);
6351     ok(val == 5, "Expected 5, got %d\n", val);
6352
6353     val = MsiRecordGetInteger(hrec, 2);
6354     ok(val == 14, "Expected 14, got %d\n", val);
6355
6356     MsiCloseHandle(hrec);
6357
6358     r = MsiViewFetch(hview, &hrec);
6359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6360
6361     val = MsiRecordGetInteger(hrec, 1);
6362     ok(val == 1, "Expected 1, got %d\n", val);
6363
6364     val = MsiRecordGetInteger(hrec, 2);
6365     ok(val == 10, "Expected 10, got %d\n", val);
6366
6367     MsiCloseHandle(hrec);
6368
6369     r = MsiViewFetch(hview, &hrec);
6370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6371
6372     val = MsiRecordGetInteger(hrec, 1);
6373     ok(val == 3, "Expected 3, got %d\n", val);
6374
6375     val = MsiRecordGetInteger(hrec, 2);
6376     ok(val == 10, "Expected 10, got %d\n", val);
6377
6378     MsiCloseHandle(hrec);
6379
6380     r = MsiViewFetch(hview, &hrec);
6381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6382
6383     val = MsiRecordGetInteger(hrec, 1);
6384     ok(val == 5, "Expected 5, got %d\n", val);
6385
6386     val = MsiRecordGetInteger(hrec, 2);
6387     ok(val == 10, "Expected 10, got %d\n", val);
6388
6389     MsiCloseHandle(hrec);
6390
6391     r = MsiViewFetch(hview, &hrec);
6392     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6393
6394     MsiViewClose(hview);
6395     MsiCloseHandle(hview);
6396
6397     query = "SELECT * FROM `Empty` ORDER BY `A`";
6398     r = MsiDatabaseOpenView(hdb, query, &hview);
6399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6400     r = MsiViewExecute(hview, 0);
6401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6402
6403     r = MsiViewFetch(hview, &hrec);
6404     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6405
6406     MsiViewClose(hview);
6407     MsiCloseHandle(hview);
6408
6409     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6410     r = run_query(hdb, 0, query);
6411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6412
6413     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6414     r = run_query(hdb, 0, query);
6415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6416
6417     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6418     r = run_query(hdb, 0, query);
6419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6420
6421     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6422     r = run_query(hdb, 0, query);
6423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6424
6425     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6426     r = MsiDatabaseOpenView(hdb, query, &hview);
6427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6428     r = MsiViewExecute(hview, 0);
6429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6430
6431     r = MsiViewFetch(hview, &hrec);
6432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6433
6434     sz = sizeof(buffer);
6435     r = MsiRecordGetString(hrec, 1, buffer, &sz);
6436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6437     ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6438
6439     r = MsiRecordGetInteger(hrec, 2);
6440     ok(r == 3, "Expected 3, got %d\n", r);
6441
6442     MsiCloseHandle(hrec);
6443
6444     r = MsiViewFetch(hview, &hrec);
6445     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6446
6447     MsiViewClose(hview);
6448     MsiCloseHandle(hview);
6449     MsiCloseHandle(hdb);
6450 }
6451
6452 static void test_viewmodify_delete_temporary(void)
6453 {
6454     MSIHANDLE hdb, hview, hrec;
6455     const char *query;
6456     UINT r;
6457
6458     DeleteFile(msifile);
6459
6460     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6462
6463     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6464     r = run_query(hdb, 0, query);
6465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6466
6467     query = "SELECT * FROM `Table`";
6468     r = MsiDatabaseOpenView(hdb, query, &hview);
6469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6470     r = MsiViewExecute(hview, 0);
6471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6472
6473     hrec = MsiCreateRecord(1);
6474     MsiRecordSetInteger(hrec, 1, 1);
6475
6476     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6478
6479     MsiCloseHandle(hrec);
6480
6481     hrec = MsiCreateRecord(1);
6482     MsiRecordSetInteger(hrec, 1, 2);
6483
6484     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6485     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6486
6487     MsiCloseHandle(hrec);
6488
6489     hrec = MsiCreateRecord(1);
6490     MsiRecordSetInteger(hrec, 1, 3);
6491
6492     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6494
6495     MsiCloseHandle(hrec);
6496
6497     hrec = MsiCreateRecord(1);
6498     MsiRecordSetInteger(hrec, 1, 4);
6499
6500     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6502
6503     MsiCloseHandle(hrec);
6504     MsiViewClose(hview);
6505     MsiCloseHandle(hview);
6506
6507     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6508     r = MsiDatabaseOpenView(hdb, query, &hview);
6509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6510     r = MsiViewExecute(hview, 0);
6511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6512     r = MsiViewFetch(hview, &hrec);
6513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6514
6515     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6517
6518     MsiCloseHandle(hrec);
6519     MsiViewClose(hview);
6520     MsiCloseHandle(hview);
6521
6522     query = "SELECT * FROM `Table` WHERE  `A` = 3";
6523     r = MsiDatabaseOpenView(hdb, query, &hview);
6524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6525     r = MsiViewExecute(hview, 0);
6526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6527     r = MsiViewFetch(hview, &hrec);
6528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6529
6530     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6532
6533     MsiCloseHandle(hrec);
6534     MsiViewClose(hview);
6535     MsiCloseHandle(hview);
6536
6537     query = "SELECT * FROM `Table` ORDER BY `A`";
6538     r = MsiDatabaseOpenView(hdb, query, &hview);
6539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6540     r = MsiViewExecute(hview, 0);
6541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6542
6543     r = MsiViewFetch(hview, &hrec);
6544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6545
6546     r = MsiRecordGetInteger(hrec, 1);
6547     ok(r == 1, "Expected 1, got %d\n", r);
6548
6549     MsiCloseHandle(hrec);
6550
6551     r = MsiViewFetch(hview, &hrec);
6552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6553
6554     r = MsiRecordGetInteger(hrec, 1);
6555     ok(r == 4, "Expected 4, got %d\n", r);
6556
6557     MsiCloseHandle(hrec);
6558
6559     r = MsiViewFetch(hview, &hrec);
6560     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6561
6562     MsiViewClose(hview);
6563     MsiCloseHandle(hview);
6564     MsiCloseHandle(hdb);
6565     DeleteFileA(msifile);
6566 }
6567
6568 static void test_deleterow(void)
6569 {
6570     MSIHANDLE hdb, hview, hrec;
6571     const char *query;
6572     char buf[MAX_PATH];
6573     UINT r;
6574     DWORD size;
6575
6576     DeleteFile(msifile);
6577
6578     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6579     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6580
6581     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6582     r = run_query(hdb, 0, query);
6583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6584
6585     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6586     r = run_query(hdb, 0, query);
6587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6588
6589     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6590     r = run_query(hdb, 0, query);
6591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6592
6593     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6594     r = run_query(hdb, 0, query);
6595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6596
6597     r = MsiDatabaseCommit(hdb);
6598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6599
6600     MsiCloseHandle(hdb);
6601
6602     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
6603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6604
6605     query = "SELECT * FROM `Table`";
6606     r = MsiDatabaseOpenView(hdb, query, &hview);
6607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6608     r = MsiViewExecute(hview, 0);
6609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6610
6611     r = MsiViewFetch(hview, &hrec);
6612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6613
6614     size = MAX_PATH;
6615     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6617     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6618
6619     MsiCloseHandle(hrec);
6620
6621     r = MsiViewFetch(hview, &hrec);
6622     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6623
6624     MsiViewClose(hview);
6625     MsiCloseHandle(hview);
6626     MsiCloseHandle(hdb);
6627     DeleteFileA(msifile);
6628 }
6629
6630 static const CHAR import_dat[] = "A\n"
6631                                  "s72\n"
6632                                  "Table\tA\n"
6633                                  "This is a new 'string' ok\n";
6634
6635 static void test_quotes(void)
6636 {
6637     MSIHANDLE hdb, hview, hrec;
6638     const char *query;
6639     char buf[MAX_PATH];
6640     UINT r;
6641     DWORD size;
6642
6643     DeleteFile(msifile);
6644
6645     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6646     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6647
6648     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6649     r = run_query(hdb, 0, query);
6650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6651
6652     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6653     r = run_query(hdb, 0, query);
6654     ok(r == ERROR_BAD_QUERY_SYNTAX,
6655        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6656
6657     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6658     r = run_query(hdb, 0, query);
6659     ok(r == ERROR_BAD_QUERY_SYNTAX,
6660        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6661
6662     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6663     r = run_query(hdb, 0, query);
6664     ok(r == ERROR_BAD_QUERY_SYNTAX,
6665        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6666
6667     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6668     r = run_query(hdb, 0, query);
6669     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6670
6671     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6672     r = run_query(hdb, 0, query);
6673     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6674
6675     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6676     r = run_query(hdb, 0, query);
6677     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6678
6679     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6680     r = run_query(hdb, 0, query);
6681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6682
6683     query = "SELECT * FROM `Table`";
6684     r = MsiDatabaseOpenView(hdb, query, &hview);
6685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6686
6687     r = MsiViewExecute(hview, 0);
6688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6689
6690     r = MsiViewFetch(hview, &hrec);
6691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6692
6693     size = MAX_PATH;
6694     r = MsiRecordGetString(hrec, 1, buf, &size);
6695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6696     ok(!lstrcmp(buf, "This is a \"string\" ok"),
6697        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6698
6699     MsiCloseHandle(hrec);
6700
6701     r = MsiViewFetch(hview, &hrec);
6702     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6703
6704     MsiViewClose(hview);
6705     MsiCloseHandle(hview);
6706
6707     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6708
6709     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6711
6712     DeleteFileA("import.idt");
6713
6714     query = "SELECT * FROM `Table`";
6715     r = MsiDatabaseOpenView(hdb, query, &hview);
6716     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6717
6718     r = MsiViewExecute(hview, 0);
6719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6720
6721     r = MsiViewFetch(hview, &hrec);
6722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6723
6724     size = MAX_PATH;
6725     r = MsiRecordGetString(hrec, 1, buf, &size);
6726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6727     ok(!lstrcmp(buf, "This is a new 'string' ok"),
6728        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6729
6730     MsiCloseHandle(hrec);
6731
6732     r = MsiViewFetch(hview, &hrec);
6733     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6734
6735     MsiViewClose(hview);
6736     MsiCloseHandle(hview);
6737     MsiCloseHandle(hdb);
6738     DeleteFileA(msifile);
6739 }
6740
6741 static void test_carriagereturn(void)
6742 {
6743     MSIHANDLE hdb, hview, hrec;
6744     const char *query;
6745     char buf[MAX_PATH];
6746     UINT r;
6747     DWORD size;
6748
6749     DeleteFile(msifile);
6750
6751     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6753
6754     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6755     r = run_query(hdb, 0, query);
6756     ok(r == ERROR_BAD_QUERY_SYNTAX,
6757        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6758
6759     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6760     r = run_query(hdb, 0, query);
6761     ok(r == ERROR_BAD_QUERY_SYNTAX,
6762        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6763
6764     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6765     r = run_query(hdb, 0, query);
6766     ok(r == ERROR_BAD_QUERY_SYNTAX,
6767        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6768
6769     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6770     r = run_query(hdb, 0, query);
6771     ok(r == ERROR_BAD_QUERY_SYNTAX,
6772        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6773
6774     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6775     r = run_query(hdb, 0, query);
6776     ok(r == ERROR_BAD_QUERY_SYNTAX,
6777        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6778
6779     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6780     r = run_query(hdb, 0, query);
6781     ok(r == ERROR_BAD_QUERY_SYNTAX,
6782        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6783
6784     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6785     r = run_query(hdb, 0, query);
6786     ok(r == ERROR_BAD_QUERY_SYNTAX,
6787        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6788
6789     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6790     r = run_query(hdb, 0, query);
6791     ok(r == ERROR_BAD_QUERY_SYNTAX,
6792        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6793
6794     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6795     r = run_query(hdb, 0, query);
6796     ok(r == ERROR_BAD_QUERY_SYNTAX,
6797        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6798
6799     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6800     r = run_query(hdb, 0, query);
6801     ok(r == ERROR_BAD_QUERY_SYNTAX,
6802        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6803
6804     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6805     r = run_query(hdb, 0, query);
6806     ok(r == ERROR_BAD_QUERY_SYNTAX,
6807        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6808
6809     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6810     r = run_query(hdb, 0, query);
6811     ok(r == ERROR_BAD_QUERY_SYNTAX,
6812        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6813
6814     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6815     r = run_query(hdb, 0, query);
6816     ok(r == ERROR_BAD_QUERY_SYNTAX,
6817        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6818
6819     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6820     r = run_query(hdb, 0, query);
6821     ok(r == ERROR_BAD_QUERY_SYNTAX,
6822        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6823
6824     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6825     r = run_query(hdb, 0, query);
6826     ok(r == ERROR_BAD_QUERY_SYNTAX,
6827        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6828
6829     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6830     r = run_query(hdb, 0, query);
6831     ok(r == ERROR_BAD_QUERY_SYNTAX,
6832        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6833
6834     query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6835     r = run_query(hdb, 0, query);
6836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6837
6838     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6839     r = run_query(hdb, 0, query);
6840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6841
6842     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6843     r = run_query(hdb, 0, query);
6844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6845
6846     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6847     r = run_query(hdb, 0, query);
6848     ok(r == ERROR_BAD_QUERY_SYNTAX,
6849        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6850
6851     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6852     r = run_query(hdb, 0, query);
6853     ok(r == ERROR_BAD_QUERY_SYNTAX,
6854        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6855
6856     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6857     r = run_query(hdb, 0, query);
6858     ok(r == ERROR_BAD_QUERY_SYNTAX,
6859        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6860
6861     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6862     r = run_query(hdb, 0, query);
6863     ok(r == ERROR_BAD_QUERY_SYNTAX,
6864        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6865
6866     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6867     r = run_query(hdb, 0, query);
6868     ok(r == ERROR_BAD_QUERY_SYNTAX,
6869        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6870
6871     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6872     r = run_query(hdb, 0, query);
6873     ok(r == ERROR_BAD_QUERY_SYNTAX,
6874        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6875
6876     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6877     r = run_query(hdb, 0, query);
6878     ok(r == ERROR_BAD_QUERY_SYNTAX,
6879        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6880
6881     query = "SELECT * FROM `_Tables`";
6882     r = MsiDatabaseOpenView(hdb, query, &hview);
6883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6884     r = MsiViewExecute(hview, 0);
6885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6886
6887     r = MsiViewFetch(hview, &hrec);
6888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6889
6890     size = MAX_PATH;
6891     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6893     ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6894
6895     MsiCloseHandle(hrec);
6896
6897     r = MsiViewFetch(hview, &hrec);
6898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6899
6900     size = MAX_PATH;
6901     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6903     ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6904
6905     MsiCloseHandle(hrec);
6906
6907     r = MsiViewFetch(hview, &hrec);
6908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909
6910     size = MAX_PATH;
6911     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6913     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6914
6915     MsiCloseHandle(hrec);
6916
6917     r = MsiViewFetch(hview, &hrec);
6918     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6919
6920     MsiViewClose(hview);
6921     MsiCloseHandle(hview);
6922
6923     MsiCloseHandle(hdb);
6924     DeleteFileA(msifile);
6925 }
6926
6927 static void test_noquotes(void)
6928 {
6929     MSIHANDLE hdb, hview, hrec;
6930     const char *query;
6931     char buf[MAX_PATH];
6932     UINT r;
6933     DWORD size;
6934
6935     DeleteFile(msifile);
6936
6937     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6939
6940     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6941     r = run_query(hdb, 0, query);
6942     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6943
6944     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6945     r = run_query(hdb, 0, query);
6946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6947
6948     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6949     r = run_query(hdb, 0, query);
6950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6951
6952     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6953     r = run_query(hdb, 0, query);
6954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6955
6956     query = "SELECT * FROM `_Tables`";
6957     r = MsiDatabaseOpenView(hdb, query, &hview);
6958     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6959     r = MsiViewExecute(hview, 0);
6960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6961
6962     r = MsiViewFetch(hview, &hrec);
6963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6964
6965     size = MAX_PATH;
6966     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6968     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6969
6970     MsiCloseHandle(hrec);
6971
6972     r = MsiViewFetch(hview, &hrec);
6973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6974
6975     size = MAX_PATH;
6976     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6977     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6978     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6979
6980     MsiCloseHandle(hrec);
6981
6982     r = MsiViewFetch(hview, &hrec);
6983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6984
6985     size = MAX_PATH;
6986     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6988     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6989
6990     MsiCloseHandle(hrec);
6991
6992     r = MsiViewFetch(hview, &hrec);
6993     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6994
6995     MsiViewClose(hview);
6996     MsiCloseHandle(hview);
6997
6998     query = "SELECT * FROM `_Columns`";
6999     r = MsiDatabaseOpenView(hdb, query, &hview);
7000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7001     r = MsiViewExecute(hview, 0);
7002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7003
7004     r = MsiViewFetch(hview, &hrec);
7005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7006
7007     size = MAX_PATH;
7008     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7009     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7010     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
7011
7012     r = MsiRecordGetInteger(hrec, 2);
7013     ok(r == 1, "Expected 1, got %d\n", r);
7014
7015     size = MAX_PATH;
7016     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7018     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7019
7020     MsiCloseHandle(hrec);
7021
7022     r = MsiViewFetch(hview, &hrec);
7023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7024
7025     size = MAX_PATH;
7026     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7028     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
7029
7030     r = MsiRecordGetInteger(hrec, 2);
7031     ok(r == 1, "Expected 1, got %d\n", r);
7032
7033     size = MAX_PATH;
7034     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7036     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7037
7038     MsiCloseHandle(hrec);
7039
7040     r = MsiViewFetch(hview, &hrec);
7041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7042
7043     size = MAX_PATH;
7044     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7046     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7047
7048     r = MsiRecordGetInteger(hrec, 2);
7049     ok(r == 1, "Expected 1, got %d\n", r);
7050
7051     size = MAX_PATH;
7052     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7053     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7054     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7055
7056     MsiCloseHandle(hrec);
7057
7058     r = MsiViewFetch(hview, &hrec);
7059     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7060
7061     MsiViewClose(hview);
7062     MsiCloseHandle(hview);
7063
7064     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
7065     r = run_query(hdb, 0, query);
7066     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7067
7068     query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
7069     r = run_query(hdb, 0, query);
7070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7071
7072     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
7073     r = run_query(hdb, 0, query);
7074     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7075
7076     query = "SELECT * FROM Table WHERE `A` = 'hi'";
7077     r = run_query(hdb, 0, query);
7078     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7079
7080     query = "SELECT * FROM `Table` WHERE `A` = hi";
7081     r = run_query(hdb, 0, query);
7082     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7083
7084     query = "SELECT * FROM Table";
7085     r = run_query(hdb, 0, query);
7086     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7087
7088     query = "SELECT * FROM Table2";
7089     r = MsiDatabaseOpenView(hdb, query, &hview);
7090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7091     r = MsiViewExecute(hview, 0);
7092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7093
7094     r = MsiViewFetch(hview, &hrec);
7095     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7096
7097     MsiViewClose(hview);
7098     MsiCloseHandle(hview);
7099
7100     query = "SELECT * FROM `Table` WHERE A = 'hi'";
7101     r = MsiDatabaseOpenView(hdb, query, &hview);
7102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7103     r = MsiViewExecute(hview, 0);
7104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7105
7106     r = MsiViewFetch(hview, &hrec);
7107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7108
7109     size = MAX_PATH;
7110     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7112     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7113
7114     MsiCloseHandle(hrec);
7115
7116     r = MsiViewFetch(hview, &hrec);
7117     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7118
7119     MsiViewClose(hview);
7120     MsiCloseHandle(hview);
7121     MsiCloseHandle(hdb);
7122     DeleteFileA(msifile);
7123 }
7124
7125 static void read_file_data(LPCSTR filename, LPSTR buffer)
7126 {
7127     HANDLE file;
7128     DWORD read;
7129
7130     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
7131     ZeroMemory(buffer, MAX_PATH);
7132     ReadFile(file, buffer, MAX_PATH, &read, NULL);
7133     CloseHandle(file);
7134 }
7135
7136 static void test_forcecodepage(void)
7137 {
7138     MSIHANDLE hdb;
7139     const char *query;
7140     char buffer[MAX_PATH];
7141     UINT r;
7142
7143     DeleteFile(msifile);
7144     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
7145
7146     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7148
7149     query = "SELECT * FROM `_ForceCodepage`";
7150     r = run_query(hdb, 0, query);
7151     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7152
7153     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7154     r = run_query(hdb, 0, query);
7155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7156
7157     query = "SELECT * FROM `_ForceCodepage`";
7158     r = run_query(hdb, 0, query);
7159     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7160
7161     r = MsiDatabaseCommit(hdb);
7162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7163
7164     query = "SELECT * FROM `_ForceCodepage`";
7165     r = run_query(hdb, 0, query);
7166     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7167
7168     MsiCloseHandle(hdb);
7169
7170     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &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     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7178     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7179
7180     read_file_data("forcecodepage.idt", buffer);
7181     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7182        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7183
7184     create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7185
7186     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7188
7189     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7191
7192     read_file_data("forcecodepage.idt", buffer);
7193     ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
7194        "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7195
7196     create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
7197
7198     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7199     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_SUCCESS, got %d\n", r);
7200
7201     MsiCloseHandle(hdb);
7202     DeleteFileA(msifile);
7203     DeleteFileA("forcecodepage.idt");
7204 }
7205
7206 static void test_viewmodify_refresh(void)
7207 {
7208     MSIHANDLE hdb, hview, hrec;
7209     const char *query;
7210     char buffer[MAX_PATH];
7211     UINT r;
7212     DWORD size;
7213
7214     DeleteFile(msifile);
7215
7216     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7218
7219     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7220     r = run_query(hdb, 0, query);
7221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7222
7223     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7224     r = run_query(hdb, 0, query);
7225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7226
7227     query = "SELECT * FROM `Table`";
7228     r = MsiDatabaseOpenView(hdb, query, &hview);
7229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7230     r = MsiViewExecute(hview, 0);
7231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7232
7233     r = MsiViewFetch(hview, &hrec);
7234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7235
7236     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7237     r = run_query(hdb, 0, query);
7238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7239
7240     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7242
7243     size = MAX_PATH;
7244     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7246     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7247     ok(size == 2, "Expected 2, got %d\n", size);
7248
7249     r = MsiRecordGetInteger(hrec, 2);
7250     ok(r == 2, "Expected 2, got %d\n", r);
7251
7252     MsiCloseHandle(hrec);
7253     MsiViewClose(hview);
7254     MsiCloseHandle(hview);
7255
7256     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7257     r = run_query(hdb, 0, query);
7258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7259
7260     query = "SELECT * FROM `Table` WHERE `B` = 3";
7261     r = MsiDatabaseOpenView(hdb, query, &hview);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263     r = MsiViewExecute(hview, 0);
7264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7265
7266     r = MsiViewFetch(hview, &hrec);
7267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7268
7269     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7270     r = run_query(hdb, 0, query);
7271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7272
7273     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7274     r = run_query(hdb, 0, query);
7275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7276
7277     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7279
7280     size = MAX_PATH;
7281     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7283     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7284     ok(size == 5, "Expected 5, got %d\n", size);
7285
7286     r = MsiRecordGetInteger(hrec, 2);
7287     ok(r == 2, "Expected 2, got %d\n", r);
7288
7289     MsiCloseHandle(hrec);
7290     MsiViewClose(hview);
7291     MsiCloseHandle(hview);
7292     MsiCloseHandle(hdb);
7293     DeleteFileA(msifile);
7294 }
7295
7296 static void test_where_viewmodify(void)
7297 {
7298     MSIHANDLE hdb, hview, hrec;
7299     const char *query;
7300     UINT r;
7301
7302     DeleteFile(msifile);
7303
7304     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7306
7307     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7308     r = run_query(hdb, 0, query);
7309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7310
7311     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7312     r = run_query(hdb, 0, query);
7313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7314
7315     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7316     r = run_query(hdb, 0, query);
7317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7318
7319     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7320     r = run_query(hdb, 0, query);
7321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7322
7323     /* `B` = 3 doesn't match, but the view shouldn't be executed */
7324     query = "SELECT * FROM `Table` WHERE `B` = 3";
7325     r = MsiDatabaseOpenView(hdb, query, &hview);
7326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7327
7328     hrec = MsiCreateRecord(2);
7329     MsiRecordSetInteger(hrec, 1, 7);
7330     MsiRecordSetInteger(hrec, 2, 8);
7331
7332     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7334
7335     MsiCloseHandle(hrec);
7336     MsiViewClose(hview);
7337     MsiCloseHandle(hview);
7338
7339     query = "SELECT * FROM `Table` WHERE `A` = 7";
7340     r = MsiDatabaseOpenView(hdb, query, &hview);
7341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7342     r = MsiViewExecute(hview, 0);
7343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7344
7345     r = MsiViewFetch(hview, &hrec);
7346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7347
7348     r = MsiRecordGetInteger(hrec, 1);
7349     ok(r == 7, "Expected 7, got %d\n", r);
7350
7351     r = MsiRecordGetInteger(hrec, 2);
7352     ok(r == 8, "Expected 8, got %d\n", r);
7353
7354     MsiRecordSetInteger(hrec, 2, 9);
7355
7356     r = MsiViewModify(hview, MSIMODIFY_UPDATE, 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 == 9, "Expected 9, got %d\n", r);
7377
7378     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7379     r = run_query(hdb, 0, query);
7380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7381
7382     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7384
7385     r = MsiRecordGetInteger(hrec, 1);
7386     ok(r == 7, "Expected 7, got %d\n", r);
7387
7388     r = MsiRecordGetInteger(hrec, 2);
7389     ok(r == 10, "Expected 10, got %d\n", r);
7390
7391     MsiCloseHandle(hrec);
7392     MsiViewClose(hview);
7393     MsiCloseHandle(hview);
7394     MsiCloseHandle(hdb);
7395 }
7396
7397 static BOOL create_storage(LPCSTR name)
7398 {
7399     WCHAR nameW[MAX_PATH];
7400     IStorage *stg;
7401     IStream *stm;
7402     HRESULT hr;
7403     DWORD count;
7404     BOOL res = FALSE;
7405
7406     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7407     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7408                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7409     if (FAILED(hr))
7410         return FALSE;
7411
7412     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7413                                0, 0, &stm);
7414     if (FAILED(hr))
7415         goto done;
7416
7417     hr = IStream_Write(stm, "stgdata", 8, &count);
7418     if (SUCCEEDED(hr))
7419         res = TRUE;
7420
7421 done:
7422     IStream_Release(stm);
7423     IStorage_Release(stg);
7424
7425     return res;
7426 }
7427
7428 static void test_storages_table(void)
7429 {
7430     MSIHANDLE hdb, hview, hrec;
7431     IStorage *stg, *inner;
7432     IStream *stm;
7433     char file[MAX_PATH];
7434     char buf[MAX_PATH];
7435     WCHAR name[MAX_PATH];
7436     LPCSTR query;
7437     HRESULT hr;
7438     DWORD size;
7439     UINT r;
7440
7441     hdb = create_db();
7442     ok(hdb, "failed to create db\n");
7443
7444     r = MsiDatabaseCommit(hdb);
7445     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7446
7447     MsiCloseHandle(hdb);
7448
7449     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
7450     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7451
7452     /* check the column types */
7453     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7454     ok(hrec, "failed to get column info hrecord\n");
7455     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7456     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7457
7458     MsiCloseHandle(hrec);
7459
7460     /* now try the names */
7461     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7462     ok(hrec, "failed to get column info hrecord\n");
7463     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7464     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7465
7466     MsiCloseHandle(hrec);
7467
7468     create_storage("storage.bin");
7469
7470     hrec = MsiCreateRecord(2);
7471     MsiRecordSetString(hrec, 1, "stgname");
7472
7473     r = MsiRecordSetStream(hrec, 2, "storage.bin");
7474     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7475
7476     DeleteFileA("storage.bin");
7477
7478     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7479     r = MsiDatabaseOpenView(hdb, query, &hview);
7480     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7481
7482     r = MsiViewExecute(hview, hrec);
7483     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7484
7485     MsiCloseHandle(hrec);
7486     MsiViewClose(hview);
7487     MsiCloseHandle(hview);
7488
7489     query = "SELECT `Name`, `Data` FROM `_Storages`";
7490     r = MsiDatabaseOpenView(hdb, query, &hview);
7491     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7492
7493     r = MsiViewExecute(hview, 0);
7494     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7495
7496     r = MsiViewFetch(hview, &hrec);
7497     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7498
7499     size = MAX_PATH;
7500     r = MsiRecordGetString(hrec, 1, file, &size);
7501     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7502     ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7503
7504     size = MAX_PATH;
7505     lstrcpyA(buf, "apple");
7506     r = MsiRecordReadStream(hrec, 2, buf, &size);
7507     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7508     ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7509     ok(size == 0, "Expected 0, got %d\n", size);
7510
7511     MsiCloseHandle(hrec);
7512
7513     r = MsiViewFetch(hview, &hrec);
7514     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7515
7516     MsiViewClose(hview);
7517     MsiCloseHandle(hview);
7518
7519     MsiDatabaseCommit(hdb);
7520     MsiCloseHandle(hdb);
7521
7522     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7523     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7524                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7525     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7526     ok(stg != NULL, "Expected non-NULL storage\n");
7527
7528     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7529     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7530                               NULL, 0, &inner);
7531     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7532     ok(inner != NULL, "Expected non-NULL storage\n");
7533
7534     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7535     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7536     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7537     ok(stm != NULL, "Expected non-NULL stream\n");
7538
7539     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7540     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7541     ok(size == 8, "Expected 8, got %d\n", size);
7542     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7543
7544     IStream_Release(stm);
7545     IStorage_Release(inner);
7546
7547     IStorage_Release(stg);
7548     DeleteFileA(msifile);
7549 }
7550
7551 static void test_dbtopackage(void)
7552 {
7553     MSIHANDLE hdb, hpkg;
7554     CHAR package[12], buf[MAX_PATH];
7555     DWORD size;
7556     UINT r;
7557
7558     /* create an empty database, transact mode */
7559     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7560     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7561
7562     set_summary_info(hdb);
7563
7564     r = create_directory_table(hdb);
7565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7566
7567     r = create_custom_action_table(hdb);
7568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7569
7570     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7572
7573     sprintf(package, "#%u", hdb);
7574     r = MsiOpenPackage(package, &hpkg);
7575     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7576     {
7577         skip("Not enough rights to perform tests\n");
7578         goto error;
7579     }
7580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7581
7582     /* property is not set yet */
7583     size = MAX_PATH;
7584     lstrcpyA(buf, "kiwi");
7585     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7587     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7588     ok(size == 0, "Expected 0, got %d\n", size);
7589
7590     /* run the custom action to set the property */
7591     r = MsiDoAction(hpkg, "SetProp");
7592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7593
7594     /* property is now set */
7595     size = MAX_PATH;
7596     lstrcpyA(buf, "kiwi");
7597     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7599     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7600     ok(size == 5, "Expected 5, got %d\n", size);
7601
7602     MsiCloseHandle(hpkg);
7603
7604     /* reset the package */
7605     r = MsiOpenPackage(package, &hpkg);
7606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7607
7608     /* property is not set anymore */
7609     size = MAX_PATH;
7610     lstrcpyA(buf, "kiwi");
7611     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7613     todo_wine
7614     {
7615         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7616         ok(size == 0, "Expected 0, got %d\n", size);
7617     }
7618
7619     MsiCloseHandle(hdb);
7620     MsiCloseHandle(hpkg);
7621
7622     /* create an empty database, direct mode */
7623     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
7624     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7625
7626     set_summary_info(hdb);
7627
7628     r = create_directory_table(hdb);
7629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7630
7631     r = create_custom_action_table(hdb);
7632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7633
7634     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7636
7637     sprintf(package, "#%u", hdb);
7638     r = MsiOpenPackage(package, &hpkg);
7639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7640
7641     /* property is not set yet */
7642     size = MAX_PATH;
7643     lstrcpyA(buf, "kiwi");
7644     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7646     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7647     ok(size == 0, "Expected 0, got %d\n", size);
7648
7649     /* run the custom action to set the property */
7650     r = MsiDoAction(hpkg, "SetProp");
7651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7652
7653     /* property is now set */
7654     size = MAX_PATH;
7655     lstrcpyA(buf, "kiwi");
7656     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7658     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7659     ok(size == 5, "Expected 5, got %d\n", size);
7660
7661     MsiCloseHandle(hpkg);
7662
7663     /* reset the package */
7664     r = MsiOpenPackage(package, &hpkg);
7665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7666
7667     /* property is not set anymore */
7668     size = MAX_PATH;
7669     lstrcpyA(buf, "kiwi");
7670     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7672     todo_wine
7673     {
7674         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7675         ok(size == 0, "Expected 0, got %d\n", size);
7676     }
7677
7678     MsiCloseHandle(hpkg);
7679
7680 error:
7681     MsiCloseHandle(hdb);
7682     DeleteFileA(msifile);
7683 }
7684
7685 static void test_droptable(void)
7686 {
7687     MSIHANDLE hdb, hview, hrec;
7688     CHAR buf[MAX_PATH];
7689     LPCSTR query;
7690     DWORD size;
7691     UINT r;
7692
7693     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7695
7696     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7697     r = run_query(hdb, 0, query);
7698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7699
7700     query = "SELECT * FROM `One`";
7701     r = do_query(hdb, query, &hrec);
7702     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7703
7704     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7705     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7707     r = MsiViewExecute(hview, 0);
7708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7709
7710     r = MsiViewFetch(hview, &hrec);
7711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7712
7713     size = MAX_PATH;
7714     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7716     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7717
7718     MsiCloseHandle(hrec);
7719     MsiViewClose(hview);
7720     MsiCloseHandle(hview);
7721
7722     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7723     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7725     r = MsiViewExecute(hview, 0);
7726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7727
7728     r = MsiViewFetch(hview, &hrec);
7729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7730
7731     size = MAX_PATH;
7732     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7734     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7735
7736     r = MsiRecordGetInteger(hrec, 2);
7737     ok(r == 1, "Expected 1, got %d\n", r);
7738
7739     size = MAX_PATH;
7740     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7741     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7742     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7743
7744     MsiCloseHandle(hrec);
7745
7746     r = MsiViewFetch(hview, &hrec);
7747     ok(r == ERROR_NO_MORE_ITEMS,
7748        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7749
7750     MsiViewClose(hview);
7751     MsiCloseHandle(hview);
7752
7753     query = "DROP `One`";
7754     r = run_query(hdb, 0, query);
7755     ok(r == ERROR_BAD_QUERY_SYNTAX,
7756        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7757
7758     query = "DROP TABLE";
7759     r = run_query(hdb, 0, query);
7760     ok(r == ERROR_BAD_QUERY_SYNTAX,
7761        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7762
7763     query = "DROP TABLE `One`";
7764     hview = 0;
7765     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7767     r = MsiViewExecute(hview, 0);
7768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7769
7770     r = MsiViewFetch(hview, &hrec);
7771     ok(r == ERROR_FUNCTION_FAILED,
7772        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7773
7774     MsiViewClose(hview);
7775     MsiCloseHandle(hview);
7776
7777     query = "SELECT * FROM `IDontExist`";
7778     r = do_query(hdb, query, &hrec);
7779     ok(r == ERROR_BAD_QUERY_SYNTAX,
7780        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7781
7782     query = "SELECT * FROM `One`";
7783     r = do_query(hdb, query, &hrec);
7784     ok(r == ERROR_BAD_QUERY_SYNTAX,
7785        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7786
7787     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7788     r = run_query(hdb, 0, query);
7789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7790
7791     query = "DROP TABLE One";
7792     r = run_query(hdb, 0, query);
7793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7794
7795     query = "SELECT * FROM `One`";
7796     r = do_query(hdb, query, &hrec);
7797     ok(r == ERROR_BAD_QUERY_SYNTAX,
7798        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7799
7800     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7801     r = do_query(hdb, query, &hrec);
7802     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7803
7804     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7805     r = do_query(hdb, query, &hrec);
7806     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7807
7808     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7809     r = run_query(hdb, 0, query);
7810     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7811
7812     query = "SELECT * FROM `One`";
7813     r = do_query(hdb, query, &hrec);
7814     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7815
7816     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7817     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7818     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7819     r = MsiViewExecute(hview, 0);
7820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7821
7822     r = MsiViewFetch(hview, &hrec);
7823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7824
7825     size = MAX_PATH;
7826     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7828     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7829
7830     MsiCloseHandle(hrec);
7831     MsiViewClose(hview);
7832     MsiCloseHandle(hview);
7833
7834     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7835     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7837     r = MsiViewExecute(hview, 0);
7838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7839
7840     r = MsiViewFetch(hview, &hrec);
7841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7842
7843     size = MAX_PATH;
7844     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7845     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7846     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7847
7848     r = MsiRecordGetInteger(hrec, 2);
7849     ok(r == 1, "Expected 1, got %d\n", r);
7850
7851     size = MAX_PATH;
7852     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7854     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7855
7856     MsiCloseHandle(hrec);
7857
7858     r = MsiViewFetch(hview, &hrec);
7859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7860
7861     size = MAX_PATH;
7862     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7864     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7865
7866     r = MsiRecordGetInteger(hrec, 2);
7867     ok(r == 2, "Expected 2, got %d\n", r);
7868
7869     size = MAX_PATH;
7870     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7872     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7873
7874     MsiCloseHandle(hrec);
7875
7876     r = MsiViewFetch(hview, &hrec);
7877     ok(r == ERROR_NO_MORE_ITEMS,
7878        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7879
7880     MsiViewClose(hview);
7881     MsiCloseHandle(hview);
7882
7883     query = "DROP TABLE One";
7884     r = run_query(hdb, 0, query);
7885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7886
7887     query = "SELECT * FROM `One`";
7888     r = do_query(hdb, query, &hrec);
7889     ok(r == ERROR_BAD_QUERY_SYNTAX,
7890        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7891
7892     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7893     r = do_query(hdb, query, &hrec);
7894     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7895
7896     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7897     r = do_query(hdb, query, &hrec);
7898     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7899
7900     MsiCloseHandle(hdb);
7901     DeleteFileA(msifile);
7902 }
7903
7904 static void test_dbmerge(void)
7905 {
7906     MSIHANDLE hdb, href, hview, hrec;
7907     CHAR buf[MAX_PATH];
7908     LPCSTR query;
7909     DWORD size;
7910     UINT r;
7911
7912     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7913     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7914
7915     r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
7916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7917
7918     /* hDatabase is invalid */
7919     r = MsiDatabaseMergeA(0, href, "MergeErrors");
7920     ok(r == ERROR_INVALID_HANDLE,
7921        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7922
7923     /* hDatabaseMerge is invalid */
7924     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7925     ok(r == ERROR_INVALID_HANDLE,
7926        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7927
7928     /* szTableName is NULL */
7929     r = MsiDatabaseMergeA(hdb, href, NULL);
7930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7931
7932     /* szTableName is empty */
7933     r = MsiDatabaseMergeA(hdb, href, "");
7934     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7935
7936     /* both DBs empty, szTableName is valid */
7937     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7939
7940     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7941     r = run_query(hdb, 0, query);
7942     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7943
7944     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7945     r = run_query(href, 0, query);
7946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7947
7948     /* column types don't match */
7949     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7950     ok(r == ERROR_DATATYPE_MISMATCH,
7951        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7952
7953     /* nothing in MergeErrors */
7954     query = "SELECT * FROM `MergeErrors`";
7955     r = do_query(hdb, query, &hrec);
7956     ok(r == ERROR_BAD_QUERY_SYNTAX,
7957        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7958
7959     query = "DROP TABLE `One`";
7960     r = run_query(hdb, 0, query);
7961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7962
7963     query = "DROP TABLE `One`";
7964     r = run_query(href, 0, query);
7965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7966
7967     query = "CREATE TABLE `One` ( "
7968         "`A` CHAR(72), "
7969         "`B` CHAR(56), "
7970         "`C` CHAR(64) LOCALIZABLE, "
7971         "`D` LONGCHAR, "
7972         "`E` CHAR(72) NOT NULL, "
7973         "`F` CHAR(56) NOT NULL, "
7974         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7975         "`H` LONGCHAR NOT NULL "
7976         "PRIMARY KEY `A` )";
7977     r = run_query(hdb, 0, query);
7978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7979
7980     query = "CREATE TABLE `One` ( "
7981         "`A` CHAR(64), "
7982         "`B` CHAR(64), "
7983         "`C` CHAR(64), "
7984         "`D` CHAR(64), "
7985         "`E` CHAR(64) NOT NULL, "
7986         "`F` CHAR(64) NOT NULL, "
7987         "`G` CHAR(64) NOT NULL, "
7988         "`H` CHAR(64) NOT NULL "
7989         "PRIMARY KEY `A` )";
7990     r = run_query(href, 0, query);
7991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7992
7993     /* column sting types don't match exactly */
7994     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7995     ok(r == ERROR_SUCCESS,
7996        "Expected ERROR_SUCCESS, got %d\n", r);
7997
7998     /* nothing in MergeErrors */
7999     query = "SELECT * FROM `MergeErrors`";
8000     r = do_query(hdb, query, &hrec);
8001     ok(r == ERROR_BAD_QUERY_SYNTAX,
8002        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8003
8004     query = "DROP TABLE `One`";
8005     r = run_query(hdb, 0, query);
8006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8007
8008     query = "DROP TABLE `One`";
8009     r = run_query(href, 0, query);
8010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8011
8012     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8013     r = run_query(hdb, 0, query);
8014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8015
8016     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
8017     r = run_query(href, 0, query);
8018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8019
8020     /* column names don't match */
8021     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8022     ok(r == ERROR_DATATYPE_MISMATCH,
8023        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8024
8025     /* nothing in MergeErrors */
8026     query = "SELECT * FROM `MergeErrors`";
8027     r = do_query(hdb, query, &hrec);
8028     ok(r == ERROR_BAD_QUERY_SYNTAX,
8029        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8030
8031     query = "DROP TABLE `One`";
8032     r = run_query(hdb, 0, query);
8033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8034
8035     query = "DROP TABLE `One`";
8036     r = run_query(href, 0, query);
8037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8038
8039     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8040     r = run_query(hdb, 0, query);
8041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8042
8043     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
8044     r = run_query(href, 0, query);
8045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8046
8047     /* primary keys don't match */
8048     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8049     ok(r == ERROR_DATATYPE_MISMATCH,
8050        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8051
8052     /* nothing in MergeErrors */
8053     query = "SELECT * FROM `MergeErrors`";
8054     r = do_query(hdb, query, &hrec);
8055     ok(r == ERROR_BAD_QUERY_SYNTAX,
8056        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8057
8058     query = "DROP TABLE `One`";
8059     r = run_query(hdb, 0, query);
8060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8061
8062     query = "DROP TABLE `One`";
8063     r = run_query(href, 0, query);
8064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8065
8066     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8067     r = run_query(hdb, 0, query);
8068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8069
8070     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
8071     r = run_query(href, 0, query);
8072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8073
8074     /* number of primary keys doesn't match */
8075     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8076     ok(r == ERROR_DATATYPE_MISMATCH,
8077        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8078
8079     /* nothing in MergeErrors */
8080     query = "SELECT * FROM `MergeErrors`";
8081     r = do_query(hdb, query, &hrec);
8082     ok(r == ERROR_BAD_QUERY_SYNTAX,
8083        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8084
8085     query = "DROP TABLE `One`";
8086     r = run_query(hdb, 0, query);
8087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8088
8089     query = "DROP TABLE `One`";
8090     r = run_query(href, 0, query);
8091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8092
8093     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8094     r = run_query(hdb, 0, query);
8095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8096
8097     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8098     r = run_query(href, 0, query);
8099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8100
8101     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8102     r = run_query(href, 0, query);
8103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8104
8105     /* number of columns doesn't match */
8106     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8108
8109     query = "SELECT * FROM `One`";
8110     r = do_query(hdb, query, &hrec);
8111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8112
8113     r = MsiRecordGetInteger(hrec, 1);
8114     ok(r == 1, "Expected 1, got %d\n", r);
8115
8116     r = MsiRecordGetInteger(hrec, 2);
8117     ok(r == 2, "Expected 2, got %d\n", r);
8118
8119     r = MsiRecordGetInteger(hrec, 3);
8120     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8121
8122     MsiCloseHandle(hrec);
8123
8124     /* nothing in MergeErrors */
8125     query = "SELECT * FROM `MergeErrors`";
8126     r = do_query(hdb, query, &hrec);
8127     ok(r == ERROR_BAD_QUERY_SYNTAX,
8128        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8129
8130     query = "DROP TABLE `One`";
8131     r = run_query(hdb, 0, query);
8132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8133
8134     query = "DROP TABLE `One`";
8135     r = run_query(href, 0, query);
8136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8137
8138     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8139     r = run_query(hdb, 0, query);
8140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8141
8142     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8143     r = run_query(href, 0, query);
8144     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8145
8146     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8147     r = run_query(href, 0, query);
8148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8149
8150     /* number of columns doesn't match */
8151     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8153
8154     query = "SELECT * FROM `One`";
8155     r = do_query(hdb, query, &hrec);
8156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8157
8158     r = MsiRecordGetInteger(hrec, 1);
8159     ok(r == 1, "Expected 1, got %d\n", r);
8160
8161     r = MsiRecordGetInteger(hrec, 2);
8162     ok(r == 2, "Expected 2, got %d\n", r);
8163
8164     r = MsiRecordGetInteger(hrec, 3);
8165     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8166
8167     MsiCloseHandle(hrec);
8168
8169     /* nothing in MergeErrors */
8170     query = "SELECT * FROM `MergeErrors`";
8171     r = do_query(hdb, query, &hrec);
8172     ok(r == ERROR_BAD_QUERY_SYNTAX,
8173        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8174
8175     query = "DROP TABLE `One`";
8176     r = run_query(hdb, 0, query);
8177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8178
8179     query = "DROP TABLE `One`";
8180     r = run_query(href, 0, query);
8181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8182
8183     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8184     r = run_query(hdb, 0, query);
8185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8186
8187     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
8188     r = run_query(hdb, 0, query);
8189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8190
8191     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8192     r = run_query(hdb, 0, query);
8193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8194
8195     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8196     r = run_query(href, 0, query);
8197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8198
8199     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8200     r = run_query(href, 0, query);
8201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8202
8203     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
8204     r = run_query(href, 0, query);
8205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8206
8207     /* primary keys match, rows do not */
8208     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8209     ok(r == ERROR_FUNCTION_FAILED,
8210        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8211
8212     /* nothing in MergeErrors */
8213     query = "SELECT * FROM `MergeErrors`";
8214     r = do_query(hdb, query, &hrec);
8215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8216
8217     size = MAX_PATH;
8218     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8220     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8221
8222     r = MsiRecordGetInteger(hrec, 2);
8223     ok(r == 2, "Expected 2, got %d\n", r);
8224
8225     MsiCloseHandle(hrec);
8226
8227     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8228     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8229
8230     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8232
8233     size = MAX_PATH;
8234     r = MsiRecordGetString(hrec, 1, buf, &size);
8235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8236     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8237
8238     size = MAX_PATH;
8239     r = MsiRecordGetString(hrec, 2, buf, &size);
8240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8241     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8242        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8243
8244     MsiCloseHandle(hrec);
8245
8246     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8248
8249     size = MAX_PATH;
8250     r = MsiRecordGetString(hrec, 1, buf, &size);
8251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8252     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8253
8254     size = MAX_PATH;
8255     r = MsiRecordGetString(hrec, 2, buf, &size);
8256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8257     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8258
8259     MsiCloseHandle(hrec);
8260     MsiViewClose(hview);
8261     MsiCloseHandle(hview);
8262
8263     query = "DROP TABLE `MergeErrors`";
8264     r = run_query(hdb, 0, query);
8265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8266
8267     query = "DROP TABLE `One`";
8268     r = run_query(hdb, 0, query);
8269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8270
8271     query = "DROP TABLE `One`";
8272     r = run_query(href, 0, query);
8273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8274
8275     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8276     r = run_query(href, 0, query);
8277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8278
8279     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8280     r = run_query(href, 0, query);
8281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8282
8283     /* table from merged database is not in target database */
8284     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8286
8287     query = "SELECT * FROM `One`";
8288     r = do_query(hdb, query, &hrec);
8289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8290
8291     r = MsiRecordGetInteger(hrec, 1);
8292     ok(r == 1, "Expected 1, got %d\n", r);
8293
8294     size = MAX_PATH;
8295     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8297     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8298
8299     MsiCloseHandle(hrec);
8300
8301     /* nothing in MergeErrors */
8302     query = "SELECT * FROM `MergeErrors`";
8303     r = do_query(hdb, query, &hrec);
8304     ok(r == ERROR_BAD_QUERY_SYNTAX,
8305        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8306
8307     query = "DROP TABLE `One`";
8308     r = run_query(hdb, 0, query);
8309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8310
8311     query = "DROP TABLE `One`";
8312     r = run_query(href, 0, query);
8313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8314
8315     query = "CREATE TABLE `One` ( "
8316             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8317     r = run_query(hdb, 0, query);
8318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8319
8320     query = "CREATE TABLE `One` ( "
8321             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8322     r = run_query(href, 0, query);
8323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8324
8325     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8326     r = run_query(href, 0, query);
8327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8328
8329     /* primary key is string */
8330     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8332
8333     query = "SELECT * FROM `One`";
8334     r = do_query(hdb, query, &hrec);
8335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8336
8337     size = MAX_PATH;
8338     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8340     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8341
8342     r = MsiRecordGetInteger(hrec, 2);
8343     ok(r == 1, "Expected 1, got %d\n", r);
8344
8345     MsiCloseHandle(hrec);
8346
8347     /* nothing in MergeErrors */
8348     query = "SELECT * FROM `MergeErrors`";
8349     r = do_query(hdb, query, &hrec);
8350     ok(r == ERROR_BAD_QUERY_SYNTAX,
8351        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8352
8353     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8354
8355     GetCurrentDirectoryA(MAX_PATH, buf);
8356     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8358
8359     query = "DROP TABLE `One`";
8360     r = run_query(hdb, 0, query);
8361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8362
8363     query = "DROP TABLE `One`";
8364     r = run_query(href, 0, query);
8365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8366
8367     query = "CREATE TABLE `One` ( "
8368             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8369     r = run_query(hdb, 0, query);
8370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8371
8372     query = "CREATE TABLE `One` ( "
8373             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8374     r = run_query(href, 0, query);
8375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8376
8377     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8378     r = run_query(href, 0, query);
8379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8380
8381     /* code page does not match */
8382     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8384
8385     query = "SELECT * FROM `One`";
8386     r = do_query(hdb, query, &hrec);
8387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8388
8389     r = MsiRecordGetInteger(hrec, 1);
8390     ok(r == 1, "Expected 1, got %d\n", r);
8391
8392     size = MAX_PATH;
8393     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8395     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8396
8397     MsiCloseHandle(hrec);
8398
8399     /* nothing in MergeErrors */
8400     query = "SELECT * FROM `MergeErrors`";
8401     r = do_query(hdb, query, &hrec);
8402     ok(r == ERROR_BAD_QUERY_SYNTAX,
8403        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8404
8405     query = "DROP TABLE `One`";
8406     r = run_query(hdb, 0, query);
8407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8408
8409     query = "DROP TABLE `One`";
8410     r = run_query(href, 0, query);
8411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8412
8413     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8414     r = run_query(hdb, 0, query);
8415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8416
8417     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8418     r = run_query(href, 0, query);
8419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8420
8421     create_file("binary.dat");
8422     hrec = MsiCreateRecord(1);
8423     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8424
8425     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8426     r = run_query(href, hrec, query);
8427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8428
8429     MsiCloseHandle(hrec);
8430
8431     /* binary data to merge */
8432     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8434
8435     query = "SELECT * FROM `One`";
8436     r = do_query(hdb, query, &hrec);
8437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8438
8439     r = MsiRecordGetInteger(hrec, 1);
8440     ok(r == 1, "Expected 1, got %d\n", r);
8441
8442     size = MAX_PATH;
8443     ZeroMemory(buf, MAX_PATH);
8444     r = MsiRecordReadStream(hrec, 2, buf, &size);
8445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8446     ok(!lstrcmpA(buf, "binary.dat\n"),
8447        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8448
8449     MsiCloseHandle(hrec);
8450
8451     /* nothing in MergeErrors */
8452     query = "SELECT * FROM `MergeErrors`";
8453     r = do_query(hdb, query, &hrec);
8454     ok(r == ERROR_BAD_QUERY_SYNTAX,
8455        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8456
8457     query = "DROP TABLE `One`";
8458     r = run_query(hdb, 0, query);
8459     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8460
8461     query = "DROP TABLE `One`";
8462     r = run_query(href, 0, query);
8463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8464
8465     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8466     r = run_query(hdb, 0, query);
8467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8468     r = run_query(href, 0, query);
8469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8470
8471     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8472     r = run_query(href, 0, query);
8473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8474
8475     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8476     r = run_query(href, 0, query);
8477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8478
8479     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8481
8482     query = "SELECT * FROM `One`";
8483     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8485     r = MsiViewExecute(hview, 0);
8486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8487
8488     r = MsiViewFetch(hview, &hrec);
8489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8490
8491     r = MsiRecordGetInteger(hrec, 1);
8492     ok(r == 1, "Expected 1, got %d\n", r);
8493
8494     size = MAX_PATH;
8495     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8497     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8498
8499     MsiCloseHandle(hrec);
8500
8501     r = MsiViewFetch(hview, &hrec);
8502     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8503
8504     r = MsiRecordGetInteger(hrec, 1);
8505     ok(r == 2, "Expected 2, got %d\n", r);
8506
8507     size = MAX_PATH;
8508     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8510     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8511
8512     MsiCloseHandle(hrec);
8513
8514     r = MsiViewFetch(hview, &hrec);
8515     ok(r == ERROR_NO_MORE_ITEMS,
8516        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8517
8518     MsiViewClose(hview);
8519     MsiCloseHandle(hview);
8520
8521     MsiCloseHandle(hdb);
8522     MsiCloseHandle(href);
8523     DeleteFileA(msifile);
8524     DeleteFileA("refdb.msi");
8525     DeleteFileA("codepage.idt");
8526     DeleteFileA("binary.dat");
8527 }
8528
8529 static void test_select_with_tablenames(void)
8530 {
8531     MSIHANDLE hdb, view, rec;
8532     LPCSTR query;
8533     UINT r;
8534     int i;
8535
8536     int vals[4][2] = {
8537         {1,12},
8538         {4,12},
8539         {1,15},
8540         {4,15}};
8541
8542     hdb = create_db();
8543     ok(hdb, "failed to create db\n");
8544
8545     /* Build a pair of tables with the same column names, but unique data */
8546     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8547     r = run_query(hdb, 0, query);
8548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8549
8550     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8551     r = run_query(hdb, 0, query);
8552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8553
8554     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8555     r = run_query(hdb, 0, query);
8556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8557
8558     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8559     r = run_query(hdb, 0, query);
8560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8561
8562     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8563     r = run_query(hdb, 0, query);
8564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8565
8566     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8567     r = run_query(hdb, 0, query);
8568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8569
8570
8571     /* Test that selection based on prefixing the column with the table
8572      * actually selects the right data */
8573
8574     query = "SELECT T1.A, T2.B FROM T1,T2";
8575     r = MsiDatabaseOpenView(hdb, query, &view);
8576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8577     r = MsiViewExecute(view, 0);
8578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8579
8580     for (i = 0; i < 4; i++)
8581     {
8582         r = MsiViewFetch(view, &rec);
8583         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8584
8585         r = MsiRecordGetInteger(rec, 1);
8586         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8587
8588         r = MsiRecordGetInteger(rec, 2);
8589         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8590
8591         MsiCloseHandle(rec);
8592     }
8593
8594     r = MsiViewFetch(view, &rec);
8595     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8596
8597     MsiViewClose(view);
8598     MsiCloseHandle(view);
8599     MsiCloseHandle(hdb);
8600     DeleteFileA(msifile);
8601 }
8602
8603 static const UINT ordervals[6][3] =
8604 {
8605     { MSI_NULL_INTEGER, 12, 13 },
8606     { 1, 2, 3 },
8607     { 6, 4, 5 },
8608     { 8, 9, 7 },
8609     { 10, 11, MSI_NULL_INTEGER },
8610     { 14, MSI_NULL_INTEGER, 15 }
8611 };
8612
8613 static void test_insertorder(void)
8614 {
8615     MSIHANDLE hdb, view, rec;
8616     LPCSTR query;
8617     UINT r;
8618     int i;
8619
8620     hdb = create_db();
8621     ok(hdb, "failed to create db\n");
8622
8623     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8624     r = run_query(hdb, 0, query);
8625     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8626
8627     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8628     r = run_query(hdb, 0, query);
8629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8630
8631     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8632     r = run_query(hdb, 0, query);
8633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8634
8635     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8636     r = run_query(hdb, 0, query);
8637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8638
8639     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8640     r = run_query(hdb, 0, query);
8641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8642
8643     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8644     r = run_query(hdb, 0, query);
8645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8646
8647     /* fails because the primary key already
8648      * has an MSI_NULL_INTEGER value set above
8649      */
8650     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8651     r = run_query(hdb, 0, query);
8652     ok(r == ERROR_FUNCTION_FAILED,
8653        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8654
8655     /* replicate the error where primary key is set twice */
8656     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8657     r = run_query(hdb, 0, query);
8658     ok(r == ERROR_FUNCTION_FAILED,
8659        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8660
8661     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8662     r = run_query(hdb, 0, query);
8663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8664
8665     query = "INSERT INTO `T` VALUES ( 16 )";
8666     r = run_query(hdb, 0, query);
8667     ok(r == ERROR_BAD_QUERY_SYNTAX,
8668        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8669
8670     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8671     r = run_query(hdb, 0, query);
8672     ok(r == ERROR_BAD_QUERY_SYNTAX,
8673        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8674
8675     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8676     r = run_query(hdb, 0, query);
8677     ok(r == ERROR_BAD_QUERY_SYNTAX,
8678        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8679
8680     query = "SELECT * FROM `T`";
8681     r = MsiDatabaseOpenView(hdb, query, &view);
8682     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8683     r = MsiViewExecute(view, 0);
8684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8685
8686     for (i = 0; i < 6; i++)
8687     {
8688         r = MsiViewFetch(view, &rec);
8689         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8690
8691         r = MsiRecordGetInteger(rec, 1);
8692         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8693
8694         r = MsiRecordGetInteger(rec, 2);
8695         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8696
8697         r = MsiRecordGetInteger(rec, 3);
8698         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8699
8700         MsiCloseHandle(rec);
8701     }
8702
8703     r = MsiViewFetch(view, &rec);
8704     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8705
8706     MsiViewClose(view);
8707     MsiCloseHandle(view);
8708
8709     query = "DELETE FROM `T` WHERE `A` IS NULL";
8710     r = run_query(hdb, 0, query);
8711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8712
8713     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8714     r = run_query(hdb, 0, query);
8715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8716
8717     query = "SELECT * FROM `T`";
8718     r = MsiDatabaseOpenView(hdb, query, &view);
8719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8720     r = MsiViewExecute(view, 0);
8721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8722
8723     for (i = 0; i < 6; i++)
8724     {
8725         r = MsiViewFetch(view, &rec);
8726         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8727
8728         r = MsiRecordGetInteger(rec, 1);
8729         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8730
8731         r = MsiRecordGetInteger(rec, 2);
8732         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8733
8734         r = MsiRecordGetInteger(rec, 3);
8735         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8736
8737         MsiCloseHandle(rec);
8738     }
8739
8740     r = MsiViewFetch(view, &rec);
8741     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8742
8743     MsiViewClose(view);
8744     MsiCloseHandle(view);
8745     MsiCloseHandle(hdb);
8746     DeleteFileA(msifile);
8747 }
8748
8749 static void test_columnorder(void)
8750 {
8751     MSIHANDLE hdb, view, rec;
8752     char buf[MAX_PATH];
8753     LPCSTR query;
8754     DWORD sz;
8755     UINT r;
8756
8757     hdb = create_db();
8758     ok(hdb, "failed to create db\n");
8759
8760     /* Each column is a slot:
8761      * ---------------------
8762      * | B | C | A | E | D |
8763      * ---------------------
8764      *
8765      * When a column is selected as a primary key,
8766      * the column occupying the nth primary key slot is swapped
8767      * with the current position of the primary key in question:
8768      *
8769      * set primary key `D`
8770      * ---------------------    ---------------------
8771      * | B | C | A | E | D | -> | D | C | A | E | B |
8772      * ---------------------    ---------------------
8773      *
8774      * set primary key `E`
8775      * ---------------------    ---------------------
8776      * | D | C | A | E | B | -> | D | E | A | C | B |
8777      * ---------------------    ---------------------
8778      */
8779
8780     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8781             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8782             "PRIMARY KEY `D`, `E`)";
8783     r = run_query(hdb, 0, query);
8784     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8785
8786     query = "SELECT * FROM `T`";
8787     r = MsiDatabaseOpenView(hdb, query, &view);
8788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8789
8790     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8791     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8792
8793     sz = MAX_PATH;
8794     lstrcpyA(buf, "kiwi");
8795     r = MsiRecordGetString(rec, 1, buf, &sz);
8796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8797     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8798
8799     sz = MAX_PATH;
8800     lstrcpyA(buf, "kiwi");
8801     r = MsiRecordGetString(rec, 2, buf, &sz);
8802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8803     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8804
8805     sz = MAX_PATH;
8806     lstrcpyA(buf, "kiwi");
8807     r = MsiRecordGetString(rec, 3, buf, &sz);
8808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8809     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8810
8811     sz = MAX_PATH;
8812     lstrcpyA(buf, "kiwi");
8813     r = MsiRecordGetString(rec, 4, buf, &sz);
8814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8815     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8816
8817     sz = MAX_PATH;
8818     lstrcpyA(buf, "kiwi");
8819     r = MsiRecordGetString(rec, 5, buf, &sz);
8820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8821     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8822
8823     MsiCloseHandle(rec);
8824
8825     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8827
8828     sz = MAX_PATH;
8829     lstrcpyA(buf, "kiwi");
8830     r = MsiRecordGetString(rec, 1, buf, &sz);
8831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8832     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8833
8834     sz = MAX_PATH;
8835     lstrcpyA(buf, "kiwi");
8836     r = MsiRecordGetString(rec, 2, buf, &sz);
8837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8838     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8839
8840     sz = MAX_PATH;
8841     lstrcpyA(buf, "kiwi");
8842     r = MsiRecordGetString(rec, 3, buf, &sz);
8843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8844     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8845
8846     sz = MAX_PATH;
8847     lstrcpyA(buf, "kiwi");
8848     r = MsiRecordGetString(rec, 4, buf, &sz);
8849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8850     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8851
8852     sz = MAX_PATH;
8853     lstrcpyA(buf, "kiwi");
8854     r = MsiRecordGetString(rec, 5, buf, &sz);
8855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8856     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8857
8858     MsiCloseHandle(rec);
8859     MsiViewClose(view);
8860     MsiCloseHandle(view);
8861
8862     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8863             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8864     r = run_query(hdb, 0, query);
8865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8866
8867     query = "SELECT * FROM `T`";
8868     r = do_query(hdb, query, &rec);
8869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8870
8871     sz = MAX_PATH;
8872     lstrcpyA(buf, "kiwi");
8873     r = MsiRecordGetString(rec, 1, buf, &sz);
8874     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8875     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8876
8877     r = MsiRecordGetInteger(rec, 2);
8878     ok(r == 3, "Expected 3, got %d\n", r);
8879
8880     sz = MAX_PATH;
8881     lstrcpyA(buf, "kiwi");
8882     r = MsiRecordGetString(rec, 3, buf, &sz);
8883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8884     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8885
8886     r = MsiRecordGetInteger(rec, 4);
8887     ok(r == 2, "Expected 2, got %d\n", r);
8888
8889     r = MsiRecordGetInteger(rec, 5);
8890     ok(r == 1, "Expected 1, got %d\n", r);
8891
8892     MsiCloseHandle(rec);
8893
8894     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8895     r = MsiDatabaseOpenView(hdb, query, &view);
8896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8897     r = MsiViewExecute(view, 0);
8898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8899
8900     r = MsiViewFetch(view, &rec);
8901     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8902
8903     sz = MAX_PATH;
8904     lstrcpyA(buf, "kiwi");
8905     r = MsiRecordGetString(rec, 1, buf, &sz);
8906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8907     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8908
8909     r = MsiRecordGetInteger(rec, 2);
8910     ok(r == 1, "Expected 1, got %d\n", r);
8911
8912     sz = MAX_PATH;
8913     lstrcpyA(buf, "kiwi");
8914     r = MsiRecordGetString(rec, 3, buf, &sz);
8915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8916     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8917
8918     MsiCloseHandle(rec);
8919
8920     r = MsiViewFetch(view, &rec);
8921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8922
8923     sz = MAX_PATH;
8924     lstrcpyA(buf, "kiwi");
8925     r = MsiRecordGetString(rec, 1, buf, &sz);
8926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8927     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8928
8929     r = MsiRecordGetInteger(rec, 2);
8930     ok(r == 2, "Expected 2, got %d\n", r);
8931
8932     sz = MAX_PATH;
8933     lstrcpyA(buf, "kiwi");
8934     r = MsiRecordGetString(rec, 3, buf, &sz);
8935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8936     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8937
8938     MsiCloseHandle(rec);
8939
8940     r = MsiViewFetch(view, &rec);
8941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8942
8943     sz = MAX_PATH;
8944     lstrcpyA(buf, "kiwi");
8945     r = MsiRecordGetString(rec, 1, buf, &sz);
8946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8947     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8948
8949     r = MsiRecordGetInteger(rec, 2);
8950     ok(r == 3, "Expected 3, got %d\n", r);
8951
8952     sz = MAX_PATH;
8953     lstrcpyA(buf, "kiwi");
8954     r = MsiRecordGetString(rec, 3, buf, &sz);
8955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8956     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8957
8958     MsiCloseHandle(rec);
8959
8960     r = MsiViewFetch(view, &rec);
8961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8962
8963     sz = MAX_PATH;
8964     lstrcpyA(buf, "kiwi");
8965     r = MsiRecordGetString(rec, 1, buf, &sz);
8966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8967     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8968
8969     r = MsiRecordGetInteger(rec, 2);
8970     ok(r == 4, "Expected 4, got %d\n", r);
8971
8972     sz = MAX_PATH;
8973     lstrcpyA(buf, "kiwi");
8974     r = MsiRecordGetString(rec, 3, buf, &sz);
8975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8976     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8977
8978     MsiCloseHandle(rec);
8979
8980     r = MsiViewFetch(view, &rec);
8981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8982
8983     sz = MAX_PATH;
8984     lstrcpyA(buf, "kiwi");
8985     r = MsiRecordGetString(rec, 1, buf, &sz);
8986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8987     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8988
8989     r = MsiRecordGetInteger(rec, 2);
8990     ok(r == 5, "Expected 5, got %d\n", r);
8991
8992     sz = MAX_PATH;
8993     lstrcpyA(buf, "kiwi");
8994     r = MsiRecordGetString(rec, 3, buf, &sz);
8995     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8996     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8997
8998     MsiCloseHandle(rec);
8999
9000     r = MsiViewFetch(view, &rec);
9001     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9002
9003     MsiViewClose(view);
9004     MsiCloseHandle(view);
9005
9006     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
9007             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
9008             "PRIMARY KEY `C`, `A`, `D`)";
9009     r = run_query(hdb, 0, query);
9010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9011
9012     query = "SELECT * FROM `Z`";
9013     r = MsiDatabaseOpenView(hdb, query, &view);
9014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9015
9016     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
9017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9018
9019     sz = MAX_PATH;
9020     lstrcpyA(buf, "kiwi");
9021     r = MsiRecordGetString(rec, 1, buf, &sz);
9022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9023     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9024
9025     sz = MAX_PATH;
9026     lstrcpyA(buf, "kiwi");
9027     r = MsiRecordGetString(rec, 2, buf, &sz);
9028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9029     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
9030
9031     sz = MAX_PATH;
9032     lstrcpyA(buf, "kiwi");
9033     r = MsiRecordGetString(rec, 3, buf, &sz);
9034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9035     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
9036
9037     sz = MAX_PATH;
9038     lstrcpyA(buf, "kiwi");
9039     r = MsiRecordGetString(rec, 4, buf, &sz);
9040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9041     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
9042
9043     sz = MAX_PATH;
9044     lstrcpyA(buf, "kiwi");
9045     r = MsiRecordGetString(rec, 5, 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     MsiCloseHandle(rec);
9050
9051     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
9052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9053
9054     sz = MAX_PATH;
9055     lstrcpyA(buf, "kiwi");
9056     r = MsiRecordGetString(rec, 1, buf, &sz);
9057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9058     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9059
9060     sz = MAX_PATH;
9061     lstrcpyA(buf, "kiwi");
9062     r = MsiRecordGetString(rec, 2, buf, &sz);
9063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9064     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9065
9066     sz = MAX_PATH;
9067     lstrcpyA(buf, "kiwi");
9068     r = MsiRecordGetString(rec, 3, buf, &sz);
9069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9070     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9071
9072     sz = MAX_PATH;
9073     lstrcpyA(buf, "kiwi");
9074     r = MsiRecordGetString(rec, 4, buf, &sz);
9075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9076     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9077
9078     sz = MAX_PATH;
9079     lstrcpyA(buf, "kiwi");
9080     r = MsiRecordGetString(rec, 5, buf, &sz);
9081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9082     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9083
9084     MsiCloseHandle(rec);
9085     MsiViewClose(view);
9086     MsiCloseHandle(view);
9087
9088     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
9089             "VALUES ( 1, 2, 'a', 3, 'bc' )";
9090     r = run_query(hdb, 0, query);
9091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9092
9093     query = "SELECT * FROM `Z`";
9094     r = do_query(hdb, query, &rec);
9095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9096
9097     r = MsiRecordGetInteger(rec, 1);
9098     ok(r == 2, "Expected 2, got %d\n", r);
9099
9100     sz = MAX_PATH;
9101     lstrcpyA(buf, "kiwi");
9102     r = MsiRecordGetString(rec, 2, buf, &sz);
9103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9104     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
9105
9106     sz = MAX_PATH;
9107     lstrcpyA(buf, "kiwi");
9108     r = MsiRecordGetString(rec, 3, buf, &sz);
9109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9110     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
9111
9112     r = MsiRecordGetInteger(rec, 4);
9113     ok(r == 3, "Expected 3, got %d\n", r);
9114
9115     r = MsiRecordGetInteger(rec, 5);
9116     ok(r == 1, "Expected 1, got %d\n", r);
9117
9118     MsiCloseHandle(rec);
9119
9120     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
9121     r = MsiDatabaseOpenView(hdb, query, &view);
9122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9123     r = MsiViewExecute(view, 0);
9124     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9125
9126     r = MsiViewFetch(view, &rec);
9127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9128
9129     sz = MAX_PATH;
9130     lstrcpyA(buf, "kiwi");
9131     r = MsiRecordGetString(rec, 1, buf, &sz);
9132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9133     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9134
9135     r = MsiRecordGetInteger(rec, 2);
9136     ok(r == 1, "Expected 1, got %d\n", r);
9137
9138     sz = MAX_PATH;
9139     lstrcpyA(buf, "kiwi");
9140     r = MsiRecordGetString(rec, 3, buf, &sz);
9141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9142     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9143
9144     MsiCloseHandle(rec);
9145
9146     r = MsiViewFetch(view, &rec);
9147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9148
9149     sz = MAX_PATH;
9150     lstrcpyA(buf, "kiwi");
9151     r = MsiRecordGetString(rec, 1, buf, &sz);
9152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9153     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9154
9155     r = MsiRecordGetInteger(rec, 2);
9156     ok(r == 2, "Expected 2, got %d\n", r);
9157
9158     sz = MAX_PATH;
9159     lstrcpyA(buf, "kiwi");
9160     r = MsiRecordGetString(rec, 3, buf, &sz);
9161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9162     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9163
9164     MsiCloseHandle(rec);
9165
9166     r = MsiViewFetch(view, &rec);
9167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9168
9169     sz = MAX_PATH;
9170     lstrcpyA(buf, "kiwi");
9171     r = MsiRecordGetString(rec, 1, buf, &sz);
9172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9173     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9174
9175     r = MsiRecordGetInteger(rec, 2);
9176     ok(r == 3, "Expected 3, got %d\n", r);
9177
9178     sz = MAX_PATH;
9179     lstrcpyA(buf, "kiwi");
9180     r = MsiRecordGetString(rec, 3, buf, &sz);
9181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9182     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9183
9184     MsiCloseHandle(rec);
9185
9186     r = MsiViewFetch(view, &rec);
9187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9188
9189     sz = MAX_PATH;
9190     lstrcpyA(buf, "kiwi");
9191     r = MsiRecordGetString(rec, 1, buf, &sz);
9192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9193     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9194
9195     r = MsiRecordGetInteger(rec, 2);
9196     ok(r == 4, "Expected 4, got %d\n", r);
9197
9198     sz = MAX_PATH;
9199     lstrcpyA(buf, "kiwi");
9200     r = MsiRecordGetString(rec, 3, buf, &sz);
9201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9202     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9203
9204     MsiCloseHandle(rec);
9205
9206     r = MsiViewFetch(view, &rec);
9207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9208
9209     sz = MAX_PATH;
9210     lstrcpyA(buf, "kiwi");
9211     r = MsiRecordGetString(rec, 1, buf, &sz);
9212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9213     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9214
9215     r = MsiRecordGetInteger(rec, 2);
9216     ok(r == 5, "Expected 5, got %d\n", r);
9217
9218     sz = MAX_PATH;
9219     lstrcpyA(buf, "kiwi");
9220     r = MsiRecordGetString(rec, 3, buf, &sz);
9221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9222     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9223
9224     MsiCloseHandle(rec);
9225
9226     r = MsiViewFetch(view, &rec);
9227     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9228
9229     MsiViewClose(view);
9230     MsiCloseHandle(view);
9231
9232     MsiCloseHandle(hdb);
9233     DeleteFileA(msifile);
9234 }
9235
9236 static void test_createtable(void)
9237 {
9238     MSIHANDLE hdb, htab = 0, hrec = 0;
9239     LPCSTR query;
9240     UINT res;
9241     DWORD size;
9242     char buffer[0x20];
9243
9244     hdb = create_db();
9245     ok(hdb, "failed to create db\n");
9246
9247     query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9248     res = MsiDatabaseOpenView( hdb, query, &htab );
9249     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9250     if(res == ERROR_SUCCESS )
9251     {
9252         res = MsiViewExecute( htab, hrec );
9253         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9254
9255         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9256         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9257
9258         size = sizeof(buffer);
9259         res = MsiRecordGetString(hrec, 1, buffer, &size );
9260         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9261         MsiCloseHandle( hrec );
9262
9263         res = MsiViewClose( htab );
9264         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9265
9266         res = MsiCloseHandle( htab );
9267         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9268     }
9269
9270     query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9271     res = MsiDatabaseOpenView( hdb, query, &htab );
9272     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9273     if(res == ERROR_SUCCESS )
9274     {
9275         res = MsiViewExecute( htab, 0 );
9276         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9277
9278         res = MsiViewClose( htab );
9279         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9280
9281         res = MsiCloseHandle( htab );
9282         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9283
9284         query = "SELECT * FROM `a`";
9285         res = MsiDatabaseOpenView( hdb, query, &htab );
9286         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9287
9288         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9289         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9290
9291         buffer[0] = 0;
9292         size = sizeof(buffer);
9293         res = MsiRecordGetString(hrec, 1, buffer, &size );
9294         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9295         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9296         MsiCloseHandle( hrec );
9297
9298         res = MsiViewClose( htab );
9299         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9300
9301         res = MsiCloseHandle( htab );
9302         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9303
9304         res = MsiDatabaseCommit(hdb);
9305         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9306
9307         res = MsiCloseHandle(hdb);
9308         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9309
9310         res = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
9311         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9312
9313         query = "SELECT * FROM `a`";
9314         res = MsiDatabaseOpenView( hdb, query, &htab );
9315         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9316
9317         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9318         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9319
9320         buffer[0] = 0;
9321         size = sizeof(buffer);
9322         res = MsiRecordGetString(hrec, 1, buffer, &size );
9323         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9324         todo_wine ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9325
9326         res = MsiCloseHandle( hrec );
9327         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9328
9329         res = MsiViewClose( htab );
9330         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9331
9332         res = MsiCloseHandle( htab );
9333         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9334     }
9335
9336     res = MsiDatabaseCommit(hdb);
9337     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9338
9339     res = MsiCloseHandle(hdb);
9340     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9341
9342     DeleteFileA(msifile);
9343 }
9344
9345 static void test_embedded_nulls(void)
9346 {
9347     static const char control_table[] =
9348         "Dialog\tText\n"
9349         "s72\tL0\n"
9350         "Control\tDialog\n"
9351         "LicenseAgreementDlg\ttext\x11\x19text\0text";
9352     UINT r, sz;
9353     MSIHANDLE hdb, hrec;
9354     char buffer[32];
9355
9356     r = MsiOpenDatabaseA( msifile, MSIDBOPEN_CREATE, &hdb );
9357     ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
9358
9359     GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
9360     write_file( "temp_file", control_table, sizeof(control_table) );
9361     r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
9362     ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
9363     DeleteFileA( "temp_file" );
9364
9365     r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
9366     ok( r == ERROR_SUCCESS, "query failed %u\n", r );
9367
9368     buffer[0] = 0;
9369     sz = sizeof(buffer);
9370     r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
9371     ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
9372     ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
9373
9374     MsiCloseHandle( hrec );
9375     MsiCloseHandle( hdb );
9376     DeleteFileA( msifile );
9377 }
9378
9379 static void test_select_column_names(void)
9380 {
9381     MSIHANDLE hdb = 0, rec, rec2, view;
9382     char buffer[32];
9383     UINT r, size;
9384
9385     DeleteFile(msifile);
9386
9387     r = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
9388     ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r );
9389
9390     r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)");
9391     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9392
9393     r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" );
9394     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9395
9396     r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9397     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9398
9399     r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9400     todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
9401
9402     r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9403     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9404
9405     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" );
9406     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9407
9408     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" );
9409     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9410
9411     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" );
9412     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9413
9414     r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" );
9415     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9416
9417     r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" );
9418     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9419
9420     r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" );
9421     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9422
9423     r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" );
9424     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9425
9426     r = MsiDatabaseOpenView( hdb, "SELECT '' FROM `t`", &view );
9427     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9428
9429     r = MsiViewExecute( view, 0 );
9430     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9431
9432     r = MsiViewFetch( view, &rec );
9433     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9434     r = MsiRecordGetFieldCount( rec );
9435     ok( r == 1, "got %u\n",  r );
9436     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec2 );
9437     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9438     r = MsiRecordGetFieldCount( rec2 );
9439     ok( r == 1, "got %u\n",  r );
9440     size = sizeof(buffer);
9441     memset( buffer, 0x55, sizeof(buffer) );
9442     r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9443     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9444     ok( !buffer[0], "got \"%s\"\n", buffer );
9445     MsiCloseHandle( rec2 );
9446     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec2 );
9447     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9448     r = MsiRecordGetFieldCount( rec2 );
9449     ok( r == 1, "got %u\n",  r );
9450     size = sizeof(buffer);
9451     memset( buffer, 0x55, sizeof(buffer) );
9452     r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9453     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9454     ok( !lstrcmpA( buffer, "f0" ), "got \"%s\"\n", buffer );
9455     MsiCloseHandle( rec2 );
9456
9457     size = sizeof(buffer);
9458     memset( buffer, 0x55, sizeof(buffer) );
9459     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9460     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9461     ok( !buffer[0], "got \"%s\"\n", buffer );
9462     MsiCloseHandle( rec );
9463
9464     r = MsiViewFetch( view, &rec );
9465     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9466     size = sizeof(buffer);
9467     memset( buffer, 0x55, sizeof(buffer) );
9468     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9469     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9470     ok( !buffer[0], "got \"%s\"\n", buffer );
9471     MsiCloseHandle( rec );
9472
9473     r = MsiViewFetch( view, &rec );
9474     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9475     MsiCloseHandle( rec );
9476
9477     MsiViewClose( view );
9478     MsiCloseHandle( view );
9479
9480     r = MsiDatabaseOpenView( hdb, "SELECT `a`, '' FROM `t`", &view );
9481     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9482
9483     r = MsiViewExecute( view, 0 );
9484     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9485
9486     r = MsiViewFetch( view, &rec );
9487     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9488     r = MsiRecordGetFieldCount( rec );
9489     ok( r == 2, "got %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( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9495     MsiCloseHandle( rec );
9496
9497     r = MsiViewFetch( view, &rec );
9498     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9499     size = sizeof(buffer);
9500     memset( buffer, 0x55, sizeof(buffer) );
9501     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9502     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9503     ok( !buffer[0], "got \"%s\"\n", buffer );
9504     MsiCloseHandle( rec );
9505
9506     r = MsiViewFetch( view, &rec );
9507     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9508     MsiCloseHandle( rec );
9509
9510     MsiViewClose( view );
9511     MsiCloseHandle( view );
9512
9513     r = MsiDatabaseOpenView( hdb, "SELECT '', `a` FROM `t`", &view );
9514     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9515
9516     r = MsiViewExecute( view, 0 );
9517     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9518
9519     r = MsiViewFetch( view, &rec );
9520     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9521     r = MsiRecordGetFieldCount( rec );
9522     ok( r == 2, "got %u\n",  r );
9523     size = sizeof(buffer);
9524     memset( buffer, 0x55, sizeof(buffer) );
9525     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9526     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9527     ok( !buffer[0], "got \"%s\"\n", buffer );
9528     size = sizeof(buffer);
9529     memset( buffer, 0x55, sizeof(buffer) );
9530     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9531     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9532     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9533     MsiCloseHandle( rec );
9534
9535     r = MsiViewFetch( view, &rec );
9536     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9537     size = sizeof(buffer);
9538     memset( buffer, 0x55, sizeof(buffer) );
9539     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9540     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9541     ok( !buffer[0], "got \"%s\"\n", buffer );
9542     size = sizeof(buffer);
9543     memset( buffer, 0x55, sizeof(buffer) );
9544     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9545     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9546     ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9547     MsiCloseHandle( rec );
9548
9549     r = MsiViewFetch( view, &rec );
9550     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9551     MsiCloseHandle( rec );
9552
9553     MsiViewClose( view );
9554     MsiCloseHandle( view );
9555
9556     r = MsiDatabaseOpenView( hdb, "SELECT `a`, '', `b` FROM `t`", &view );
9557     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9558
9559     r = MsiViewExecute( view, 0 );
9560     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9561
9562     r = MsiViewFetch( view, &rec );
9563     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9564     r = MsiRecordGetFieldCount( rec );
9565     ok( r == 3, "got %u\n",  r );
9566     size = sizeof(buffer);
9567     memset( buffer, 0x55, sizeof(buffer) );
9568     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9569     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9570     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9571     size = sizeof(buffer);
9572     memset( buffer, 0x55, sizeof(buffer) );
9573     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9574     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9575     ok( !buffer[0], "got \"%s\"\n", buffer );
9576     size = sizeof(buffer);
9577     memset( buffer, 0x55, sizeof(buffer) );
9578     r = MsiRecordGetStringA( rec, 3, buffer, &size );
9579     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9580     ok( !lstrcmpA( buffer, "2" ), "got \"%s\"\n", buffer );
9581     MsiCloseHandle( rec );
9582
9583     r = MsiViewFetch( view, &rec );
9584     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9585     size = sizeof(buffer);
9586     memset( buffer, 0x55, sizeof(buffer) );
9587     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9588     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9589     ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9590     size = sizeof(buffer);
9591     memset( buffer, 0x55, sizeof(buffer) );
9592     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9593     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9594     ok( !buffer[0], "got \"%s\"\n", buffer );
9595     size = sizeof(buffer);
9596     memset( buffer, 0x55, sizeof(buffer) );
9597     r = MsiRecordGetStringA( rec, 3, buffer, &size );
9598     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9599     ok( !lstrcmpA( buffer, "4" ), "got \"%s\"\n", buffer );
9600     MsiCloseHandle( rec );
9601
9602     r = MsiViewFetch( view, &rec );
9603     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9604     MsiCloseHandle( rec );
9605
9606     MsiViewClose( view );
9607     MsiCloseHandle( view );
9608
9609     r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" );
9610     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9611
9612     r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" );
9613     todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9614
9615     r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" );
9616     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9617
9618     r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" );
9619     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9620
9621     r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" );
9622     todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9623
9624     r = MsiCloseHandle( hdb );
9625     ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r);
9626 }
9627
9628 START_TEST(db)
9629 {
9630     test_msidatabase();
9631     test_msiinsert();
9632     test_msidecomposedesc();
9633     test_msibadqueries();
9634     test_viewmodify();
9635     test_viewgetcolumninfo();
9636     test_getcolinfo();
9637     test_msiexport();
9638     test_longstrings();
9639     test_streamtable();
9640     test_binary();
9641     test_where_not_in_selected();
9642     test_where();
9643     test_msiimport();
9644     test_binary_import();
9645     test_markers();
9646     test_handle_limit();
9647     test_try_transform();
9648     test_join();
9649     test_temporary_table();
9650     test_alter();
9651     test_integers();
9652     test_update();
9653     test_special_tables();
9654     test_tables_order();
9655     test_rows_order();
9656     test_select_markers();
9657     test_viewmodify_update();
9658     test_viewmodify_assign();
9659     test_stringtable();
9660     test_viewmodify_delete();
9661     test_defaultdatabase();
9662     test_order();
9663     test_viewmodify_delete_temporary();
9664     test_deleterow();
9665     test_quotes();
9666     test_carriagereturn();
9667     test_noquotes();
9668     test_forcecodepage();
9669     test_viewmodify_refresh();
9670     test_where_viewmodify();
9671     test_storages_table();
9672     test_dbtopackage();
9673     test_droptable();
9674     test_dbmerge();
9675     test_select_with_tablenames();
9676     test_insertorder();
9677     test_columnorder();
9678     test_suminfo_import();
9679     test_createtable();
9680     test_collation();
9681     test_embedded_nulls();
9682     test_select_column_names();
9683 }