dinput: SetActionMap setting the device buffer.
[wine] / dlls / msi / tests / db.c
1 /*
2  * Copyright (C) 2005 Mike McCormack for CodeWeavers
3  *
4  * A test program for MSI database files.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include <stdio.h>
24
25 #include <windows.h>
26 #include <msi.h>
27 #include <msidefs.h>
28 #include <msiquery.h>
29
30 #include <objidl.h>
31
32 #include "wine/test.h"
33
34 static const char *msifile = "winetest-db.msi";
35 static const char *msifile2 = "winetst2-db.msi";
36 static const char *mstfile = "winetst-db.mst";
37 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','-','d','b','.','m','s','i',0};
38
39 static void test_msidatabase(void)
40 {
41     MSIHANDLE hdb = 0, hdb2 = 0;
42     UINT res;
43
44     DeleteFile(msifile);
45
46     res = MsiOpenDatabase( msifile, msifile2, &hdb );
47     ok( res == ERROR_OPEN_FAILED, "expected failure\n");
48
49     res = MsiOpenDatabase( msifile, (LPSTR) 0xff, &hdb );
50     ok( res == ERROR_INVALID_PARAMETER, "expected failure\n");
51
52     res = MsiCloseHandle( hdb );
53     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
54
55     /* create an empty database */
56     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
57     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
58
59     res = MsiDatabaseCommit( hdb );
60     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
61
62     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
63
64     res = MsiCloseHandle( hdb );
65     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
66     res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
67     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
68
69     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile2 ), "database should exist\n");
70
71     res = MsiDatabaseCommit( hdb2 );
72     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
73
74     res = MsiCloseHandle( hdb2 );
75     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
76
77     res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
78     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
79
80     res = MsiCloseHandle( hdb2 );
81     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
82
83     ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile2 ), "uncommitted database should not exist\n");
84
85     res = MsiOpenDatabase( msifile, msifile2, &hdb2 );
86     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
87
88     res = MsiDatabaseCommit( hdb2 );
89     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
90
91     res = MsiCloseHandle( hdb2 );
92     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
93
94     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile2 ), "committed database should exist\n");
95
96     res = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
97     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
98
99     res = MsiCloseHandle( hdb );
100     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
101
102     res = MsiOpenDatabase( msifile, MSIDBOPEN_DIRECT, &hdb );
103     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
104
105     res = MsiCloseHandle( hdb );
106     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
107
108     res = MsiOpenDatabase( msifile, MSIDBOPEN_TRANSACT, &hdb );
109     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
110
111     res = MsiCloseHandle( hdb );
112     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
113     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
114
115     /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
116     res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
117     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
118
119     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
120
121     res = MsiCloseHandle( hdb );
122     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
123
124     ok( INVALID_FILE_ATTRIBUTES == GetFileAttributes( msifile ), "database should exist\n");
125
126     res = MsiOpenDatabase( msifile, MSIDBOPEN_CREATE, &hdb );
127     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
128
129     res = MsiDatabaseCommit( hdb );
130     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
131
132     ok( INVALID_FILE_ATTRIBUTES != GetFileAttributes( msifile ), "database should exist\n");
133
134     res = MsiCloseHandle( hdb );
135     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
136
137     res = DeleteFile( msifile2 );
138     ok( res == TRUE, "Failed to delete database\n" );
139
140     res = DeleteFile( msifile );
141     ok( res == TRUE, "Failed to delete database\n" );
142 }
143
144 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
145 {
146     MSIHANDLE hview = 0;
147     UINT r, ret;
148
149     if (phrec)
150         *phrec = 0;
151
152     /* open a select query */
153     r = MsiDatabaseOpenView(hdb, query, &hview);
154     if (r != ERROR_SUCCESS)
155         return r;
156     r = MsiViewExecute(hview, 0);
157     if (r != ERROR_SUCCESS)
158         return r;
159     ret = MsiViewFetch(hview, phrec);
160     r = MsiViewClose(hview);
161     if (r != ERROR_SUCCESS)
162         return r;
163     r = MsiCloseHandle(hview);
164     if (r != ERROR_SUCCESS)
165         return r;
166     return ret;
167 }
168
169 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
170 {
171     MSIHANDLE hview = 0;
172     UINT r;
173
174     r = MsiDatabaseOpenView(hdb, query, &hview);
175     if( r != ERROR_SUCCESS )
176         return r;
177
178     r = MsiViewExecute(hview, hrec);
179     if( r == ERROR_SUCCESS )
180         r = MsiViewClose(hview);
181     MsiCloseHandle(hview);
182     return r;
183 }
184
185 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
186 {
187     MSIHANDLE hview = 0;
188     UINT r;
189
190     r = MsiDatabaseOpenViewW(hdb, query, &hview);
191     if( r != ERROR_SUCCESS )
192         return r;
193
194     r = MsiViewExecute(hview, hrec);
195     if( r == ERROR_SUCCESS )
196         r = MsiViewClose(hview);
197     MsiCloseHandle(hview);
198     return r;
199 }
200
201 static UINT create_component_table( MSIHANDLE hdb )
202 {
203     return run_query( hdb, 0,
204             "CREATE TABLE `Component` ( "
205             "`Component` CHAR(72) NOT NULL, "
206             "`ComponentId` CHAR(38), "
207             "`Directory_` CHAR(72) NOT NULL, "
208             "`Attributes` SHORT NOT NULL, "
209             "`Condition` CHAR(255), "
210             "`KeyPath` CHAR(72) "
211             "PRIMARY KEY `Component`)" );
212 }
213
214 static UINT create_custom_action_table( MSIHANDLE hdb )
215 {
216     return run_query( hdb, 0,
217             "CREATE TABLE `CustomAction` ( "
218             "`Action` CHAR(72) NOT NULL, "
219             "`Type` SHORT NOT NULL, "
220             "`Source` CHAR(72), "
221             "`Target` CHAR(255) "
222             "PRIMARY KEY `Action`)" );
223 }
224
225 static UINT create_directory_table( MSIHANDLE hdb )
226 {
227     return run_query( hdb, 0,
228             "CREATE TABLE `Directory` ( "
229             "`Directory` CHAR(255) NOT NULL, "
230             "`Directory_Parent` CHAR(255), "
231             "`DefaultDir` CHAR(255) NOT NULL "
232             "PRIMARY KEY `Directory`)" );
233 }
234
235 static UINT create_feature_components_table( MSIHANDLE hdb )
236 {
237     return run_query( hdb, 0,
238             "CREATE TABLE `FeatureComponents` ( "
239             "`Feature_` CHAR(38) NOT NULL, "
240             "`Component_` CHAR(72) NOT NULL "
241             "PRIMARY KEY `Feature_`, `Component_` )" );
242 }
243
244 static UINT create_std_dlls_table( MSIHANDLE hdb )
245 {
246     return run_query( hdb, 0,
247             "CREATE TABLE `StdDlls` ( "
248             "`File` CHAR(255) NOT NULL, "
249             "`Binary_` CHAR(72) NOT NULL "
250             "PRIMARY KEY `File` )" );
251 }
252
253 static UINT create_binary_table( MSIHANDLE hdb )
254 {
255     return run_query( hdb, 0,
256             "CREATE TABLE `Binary` ( "
257             "`Name` CHAR(72) NOT NULL, "
258             "`Data` CHAR(72) NOT NULL "
259             "PRIMARY KEY `Name` )" );
260 }
261
262 #define make_add_entry(type, qtext) \
263     static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
264     { \
265         char insert[] = qtext; \
266         char *query; \
267         UINT sz, r; \
268         sz = strlen(values) + sizeof insert; \
269         query = HeapAlloc(GetProcessHeap(),0,sz); \
270         sprintf(query,insert,values); \
271         r = run_query( hdb, 0, query ); \
272         HeapFree(GetProcessHeap(), 0, query); \
273         return r; \
274     }
275
276 make_add_entry(component,
277                "INSERT INTO `Component`  "
278                "(`Component`, `ComponentId`, `Directory_`, "
279                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
280
281 make_add_entry(custom_action,
282                "INSERT INTO `CustomAction`  "
283                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
284
285 make_add_entry(feature_components,
286                "INSERT INTO `FeatureComponents` "
287                "(`Feature_`, `Component_`) VALUES( %s )")
288
289 make_add_entry(std_dlls,
290                "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
291
292 make_add_entry(binary,
293                "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
294
295 static void test_msiinsert(void)
296 {
297     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
298     UINT r;
299     const char *query;
300     char buf[80];
301     DWORD sz;
302
303     DeleteFile(msifile);
304
305     /* just MsiOpenDatabase should not create a file */
306     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
307     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
308
309     /* create a table */
310     query = "CREATE TABLE `phone` ( "
311             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
312             "PRIMARY KEY `id`)";
313     r = MsiDatabaseOpenView(hdb, query, &hview);
314     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
315     r = MsiViewExecute(hview, 0);
316     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
317     r = MsiViewClose(hview);
318     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
319     r = MsiCloseHandle(hview);
320     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
321
322     /* insert a value into it */
323     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
324         "VALUES('1', 'Abe', '8675309')";
325     r = MsiDatabaseOpenView(hdb, query, &hview);
326     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
327     r = MsiViewExecute(hview, 0);
328     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
329     r = MsiViewClose(hview);
330     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
331     r = MsiCloseHandle(hview);
332     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
333
334     query = "SELECT * FROM `phone` WHERE `id` = 1";
335     r = do_query(hdb, query, &hrec);
336     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
337
338     /* check the record contains what we put in it */
339     r = MsiRecordGetFieldCount(hrec);
340     ok(r == 3, "record count wrong\n");
341
342     r = MsiRecordIsNull(hrec, 0);
343     ok(r == FALSE, "field 0 not null\n");
344
345     r = MsiRecordGetInteger(hrec, 1);
346     ok(r == 1, "field 1 contents wrong\n");
347     sz = sizeof buf;
348     r = MsiRecordGetString(hrec, 2, buf, &sz);
349     ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
350     ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
351     sz = sizeof buf;
352     r = MsiRecordGetString(hrec, 3, buf, &sz);
353     ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
354     ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
355
356     r = MsiCloseHandle(hrec);
357     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
358
359     /* open a select query */
360     hrec = 100;
361     query = "SELECT * FROM `phone` WHERE `id` >= 10";
362     r = do_query(hdb, query, &hrec);
363     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
364     ok(hrec == 0, "hrec should be null\n");
365
366     r = MsiCloseHandle(hrec);
367     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
368
369     query = "SELECT * FROM `phone` WHERE `id` < 0";
370     r = do_query(hdb, query, &hrec);
371     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
372
373     query = "SELECT * FROM `phone` WHERE `id` <= 0";
374     r = do_query(hdb, query, &hrec);
375     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
376
377     query = "SELECT * FROM `phone` WHERE `id` <> 1";
378     r = do_query(hdb, query, &hrec);
379     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
380
381     query = "SELECT * FROM `phone` WHERE `id` > 10";
382     r = do_query(hdb, query, &hrec);
383     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
384
385     /* now try a few bad INSERT xqueries */
386     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
387         "VALUES(?, ?)";
388     r = MsiDatabaseOpenView(hdb, query, &hview);
389     ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
390
391     /* construct a record to insert */
392     hrec = MsiCreateRecord(4);
393     r = MsiRecordSetInteger(hrec, 1, 2);
394     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
395     r = MsiRecordSetString(hrec, 2, "Adam");
396     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
397     r = MsiRecordSetString(hrec, 3, "96905305");
398     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
399
400     /* insert another value, using a record and wildcards */
401     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
402         "VALUES(?, ?, ?)";
403     r = MsiDatabaseOpenView(hdb, query, &hview);
404     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
405
406     if (r == ERROR_SUCCESS)
407     {
408         r = MsiViewExecute(hview, hrec);
409         ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
410         r = MsiViewClose(hview);
411         ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
412         r = MsiCloseHandle(hview);
413         ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
414     }
415     r = MsiCloseHandle(hrec);
416     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
417
418     r = MsiViewFetch(0, NULL);
419     ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
420
421     r = MsiDatabaseCommit(hdb);
422     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
423
424     r = MsiCloseHandle(hdb);
425     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
426
427     r = DeleteFile(msifile);
428     ok(r == TRUE, "file didn't exist after commit\n");
429 }
430
431 typedef UINT (WINAPI *fnMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
432 static fnMsiDecomposeDescriptorA pMsiDecomposeDescriptorA;
433
434 static void test_msidecomposedesc(void)
435 {
436     char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
437     const char *desc;
438     UINT r;
439     DWORD len;
440     HMODULE hmod;
441
442     hmod = GetModuleHandle("msi.dll");
443     pMsiDecomposeDescriptorA = (fnMsiDecomposeDescriptorA)
444         GetProcAddress(hmod, "MsiDecomposeDescriptorA");
445     if (!pMsiDecomposeDescriptorA)
446         return;
447
448     /* test a valid feature descriptor */
449     desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
450     len = 0;
451     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
452     ok(r == ERROR_SUCCESS, "returned an error\n");
453     ok(len == strlen(desc), "length was wrong\n");
454     ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
455     ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
456     ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
457
458     /* test an invalid feature descriptor with too many characters */
459     desc = "']gAVn-}f(ZXfeAR6.ji"
460            "ThisWillFailIfTheresMoreThanAGuidsChars>"
461            "3w2x^IGfe?CxI5heAvk.";
462     len = 0;
463     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
464     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
465
466     /*
467      * Test a valid feature descriptor with the
468      * maximum number of characters and some trailing characters.
469      */
470     desc = "']gAVn-}f(ZXfeAR6.ji"
471            "ThisWillWorkIfTheresLTEThanAGuidsChars>"
472            "3w2x^IGfe?CxI5heAvk."
473            "extra";
474     len = 0;
475     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
476     ok(r == ERROR_SUCCESS, "returned wrong error\n");
477     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
478
479     len = 0;
480     r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
481     ok(r == ERROR_SUCCESS, "returned wrong error\n");
482     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
483
484     len = 0;
485     r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
486     ok(r == ERROR_SUCCESS, "returned wrong error\n");
487     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
488
489     len = 0;
490     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
491     ok(r == ERROR_SUCCESS, "returned wrong error\n");
492     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
493
494     len = 0;
495     r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
496     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
497     ok(len == 0, "length wrong\n");
498
499     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL);
500     ok(r == ERROR_SUCCESS, "returned wrong error\n");
501 }
502
503 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
504 {
505     MSIHANDLE htab = 0;
506     UINT res;
507
508     res = MsiDatabaseOpenView( hdb, szQuery, &htab );
509     if(res == ERROR_SUCCESS )
510     {
511         UINT r;
512
513         r = MsiViewExecute( htab, hrec );
514         if(r != ERROR_SUCCESS )
515             res = r;
516
517         r = MsiViewClose( htab );
518         if(r != ERROR_SUCCESS )
519             res = r;
520
521         r = MsiCloseHandle( htab );
522         if(r != ERROR_SUCCESS )
523             res = r;
524     }
525     return res;
526 }
527
528 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
529 {
530     return try_query_param( hdb, szQuery, 0 );
531 }
532
533 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
534 {
535     MSIHANDLE hrec = 0;
536     UINT r;
537
538     hrec = MsiCreateRecord( 1 );
539     MsiRecordSetString( hrec, 1, "Hello");
540
541     r = try_query_param( hdb, szQuery, hrec );
542
543     MsiCloseHandle( hrec );
544     return r;
545 }
546
547 static void test_msibadqueries(void)
548 {
549     MSIHANDLE hdb = 0;
550     UINT r;
551
552     DeleteFile(msifile);
553
554     /* just MsiOpenDatabase should not create a file */
555     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
556     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
557
558     r = MsiDatabaseCommit( hdb );
559     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
560
561     r = MsiCloseHandle( hdb );
562     ok(r == ERROR_SUCCESS , "Failed to close database\n");
563
564     /* open it readonly */
565     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb );
566     ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
567
568     /* add a table to it */
569     r = try_query( hdb, "select * from _Tables");
570     ok(r == ERROR_SUCCESS , "query 1 failed\n");
571
572     r = MsiCloseHandle( hdb );
573     ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
574
575     /* open it read/write */
576     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
577     ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
578
579     /* a bunch of test queries that fail with the native MSI */
580
581     r = try_query( hdb, "CREATE TABLE");
582     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
583
584     r = try_query( hdb, "CREATE TABLE `a`");
585     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
586
587     r = try_query( hdb, "CREATE TABLE `a` ()");
588     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
589
590     r = try_query( hdb, "CREATE TABLE `a` (`b`)");
591     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
592
593     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
594     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
595
596     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
597     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
598
599     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
600     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
601
602     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
603     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
604
605     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
606     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
607
608     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
609     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
610
611     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
612     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
613
614     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
615     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
616
617     r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
618     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
619
620     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
621     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
622
623     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
624     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
625
626     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
627     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
628
629     r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
630     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
631
632     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
633     ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
634
635     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
636     ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
637
638     r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
639           "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
640     ok(r == ERROR_SUCCESS , "query 4 failed\n");
641
642     r = MsiDatabaseCommit( hdb );
643     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
644
645     r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
646                           "PRIMARY KEY `foo`)");
647     ok(r == ERROR_SUCCESS , "query 4 failed\n");
648
649     r = try_insert_query( hdb, "insert into a  ( `b` ) VALUES ( ? )");
650     ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
651
652     r = MsiDatabaseCommit( hdb );
653     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
654
655     r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
656                           "PRIMARY KEY `ba`)");
657     ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
658
659     r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
660     ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
661
662     r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
663                           "PRIMARY KEY `t`)");
664     ok(r == ERROR_SUCCESS , "query 7 failed\n");
665
666     r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
667     ok(r == ERROR_SUCCESS , "query 8 failed\n");
668
669     r = try_query( hdb, "select * from c");
670     ok(r == ERROR_SUCCESS , "query failed\n");
671
672     r = try_query( hdb, "select * from c where b = 'x");
673     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
674
675     r = try_query( hdb, "select * from c where b = 'x'");
676     ok(r == ERROR_SUCCESS, "query failed\n");
677
678     r = try_query( hdb, "select * from 'c'");
679     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
680
681     r = try_query( hdb, "select * from ''");
682     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
683
684     r = try_query( hdb, "select * from c where b = x");
685     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
686
687     r = try_query( hdb, "select * from c where b = \"x\"");
688     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
689
690     r = try_query( hdb, "select * from c where b = 'x'");
691     ok(r == ERROR_SUCCESS, "query failed\n");
692
693     r = try_query( hdb, "select * from c where b = '\"x'");
694     ok(r == ERROR_SUCCESS, "query failed\n");
695
696     if (0)  /* FIXME: this query causes trouble with other tests */
697     {
698         r = try_query( hdb, "select * from c where b = '\\\'x'");
699         ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
700     }
701
702     r = try_query( hdb, "select * from 'c'");
703     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
704
705     r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
706     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
707
708     r = try_query( hdb, "SELECT * FROM \5a" );
709     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
710
711     r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
712     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
713
714     r = try_query( hdb, "SELECT * FROM a\5" );
715     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
716
717     r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
718     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
719
720     r = try_query( hdb, "SELECT * FROM -a" );
721     todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
722
723     r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
724     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
725
726     r = try_query( hdb, "SELECT * FROM a-" );
727     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
728
729     r = MsiCloseHandle( hdb );
730     ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
731
732     r = DeleteFile( msifile );
733     ok(r == TRUE, "file didn't exist after commit\n");
734 }
735
736 static void test_viewmodify(void)
737 {
738     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
739     UINT r;
740     MSIDBERROR err;
741     const char *query;
742     char buffer[0x100];
743     DWORD sz;
744
745     DeleteFile(msifile);
746
747     /* just MsiOpenDatabase should not create a file */
748     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
749     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
750
751     query = "CREATE TABLE `phone` ( "
752             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
753             "PRIMARY KEY `id`)";
754     r = run_query( hdb, 0, query );
755     ok(r == ERROR_SUCCESS, "query failed\n");
756
757     query = "CREATE TABLE `_Validation` ( "
758             "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
759             "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
760             "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
761             "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)";
762     r = run_query( hdb, 0, query );
763     ok(r == ERROR_SUCCESS, "query failed\n");
764
765     query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) "
766             "VALUES('phone', 'id', 'N')";
767     r = run_query( hdb, 0, query );
768     ok(r == ERROR_SUCCESS, "query failed\n");
769
770     /* check what the error function reports without doing anything */
771     sz = 0;
772     /* passing NULL as the 3rd param make function to crash on older platforms */
773     err = MsiViewGetError( 0, NULL, &sz );
774     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
775
776     /* open a view */
777     query = "SELECT * FROM `phone`";
778     r = MsiDatabaseOpenView(hdb, query, &hview);
779     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
780
781     /* see what happens with a good hview and bad args */
782     err = MsiViewGetError( hview, NULL, NULL );
783     ok(err == MSIDBERROR_INVALIDARG || err == MSIDBERROR_NOERROR,
784        "MsiViewGetError returns %u (expected -3)\n", err);
785     err = MsiViewGetError( hview, buffer, NULL );
786     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
787
788     /* see what happens with a zero length buffer */
789     sz = 0;
790     buffer[0] = 'x';
791     err = MsiViewGetError( hview, buffer, &sz );
792     ok(err == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
793     ok(buffer[0] == 'x', "buffer cleared\n");
794     ok(sz == 0, "size not zero\n");
795
796     /* ok this one is strange */
797     sz = 0;
798     err = MsiViewGetError( hview, NULL, &sz );
799     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
800     ok(sz == 0, "size not zero\n");
801
802     /* see if it really has an error */
803     sz = sizeof buffer;
804     buffer[0] = 'x';
805     err = MsiViewGetError( hview, buffer, &sz );
806     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
807     ok(buffer[0] == 0, "buffer not cleared\n");
808     ok(sz == 0, "size not zero\n");
809
810     r = MsiViewExecute(hview, 0);
811     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
812
813     /* try some invalid records */
814     r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
815     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
816     r = MsiViewModify(hview, -1, 0 );
817     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
818
819     /* try an small record */
820     hrec = MsiCreateRecord(1);
821     r = MsiViewModify(hview, -1, hrec );
822     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
823
824     sz = sizeof buffer;
825     buffer[0] = 'x';
826     err = MsiViewGetError( hview, buffer, &sz );
827     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
828     ok(buffer[0] == 0, "buffer not cleared\n");
829     ok(sz == 0, "size not zero\n");
830
831     r = MsiCloseHandle(hrec);
832     ok(r == ERROR_SUCCESS, "failed to close record\n");
833
834     /* insert a valid record */
835     hrec = MsiCreateRecord(3);
836
837     r = MsiRecordSetInteger(hrec, 1, 1);
838     ok(r == ERROR_SUCCESS, "failed to set integer\n");
839     r = MsiRecordSetString(hrec, 2, "bob");
840     ok(r == ERROR_SUCCESS, "failed to set string\n");
841     r = MsiRecordSetString(hrec, 3, "7654321");
842     ok(r == ERROR_SUCCESS, "failed to set string\n");
843
844     r = MsiViewExecute(hview, 0);
845     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
846     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
847     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
848
849     /* validate it */
850     r = MsiViewExecute(hview, 0);
851     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
852
853     r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec );
854     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r);
855
856     sz = sizeof buffer;
857     buffer[0] = 'x';
858     err = MsiViewGetError( hview, buffer, &sz );
859     ok(err == MSIDBERROR_DUPLICATEKEY, "MsiViewGetError returned %u\n", err);
860     ok(!strcmp(buffer, "id"), "expected \"id\" c, got \"%s\"\n", buffer);
861     ok(sz == 2, "size not 2\n");
862
863     /* insert the same thing again */
864     r = MsiViewExecute(hview, 0);
865     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
866
867     /* should fail ... */
868     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
869     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
870
871     r = MsiCloseHandle(hrec);
872     ok(r == ERROR_SUCCESS, "failed to close record\n");
873
874     r = MsiViewClose(hview);
875     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
876     r = MsiCloseHandle(hview);
877     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
878
879     query = "SELECT * FROM `phone`";
880     r = MsiDatabaseOpenView(hdb, query, &hview);
881     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
882
883     r = MsiViewExecute(hview, 0);
884     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
885
886     r = MsiViewFetch(hview, &hrec);
887     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
888
889     r = MsiRecordGetInteger(hrec, 1);
890     ok(r == 1, "Expected 1, got %d\n", r);
891
892     sz = sizeof(buffer);
893     r = MsiRecordGetString(hrec, 2, buffer, &sz);
894     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
895     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
896
897     sz = sizeof(buffer);
898     r = MsiRecordGetString(hrec, 3, buffer, &sz);
899     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
900     ok(!lstrcmp(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
901
902     /* update the view, non-primary key */
903     r = MsiRecordSetString(hrec, 3, "3141592");
904     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
905
906     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
907     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
908
909     /* do it again */
910     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
911     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
912
913     /* update the view, primary key */
914     r = MsiRecordSetInteger(hrec, 1, 5);
915     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
916
917     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
918     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
919
920     r = MsiCloseHandle(hrec);
921     ok(r == ERROR_SUCCESS, "failed to close record\n");
922
923     r = MsiViewClose(hview);
924     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
925     r = MsiCloseHandle(hview);
926     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
927
928     query = "SELECT * FROM `phone`";
929     r = MsiDatabaseOpenView(hdb, query, &hview);
930     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
931
932     r = MsiViewExecute(hview, 0);
933     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
934
935     r = MsiViewFetch(hview, &hrec);
936     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
937
938     r = MsiRecordGetInteger(hrec, 1);
939     ok(r == 1, "Expected 1, got %d\n", r);
940
941     sz = sizeof(buffer);
942     r = MsiRecordGetString(hrec, 2, buffer, &sz);
943     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
944     ok(!lstrcmp(buffer, "bob"), "Expected bob, got %s\n", buffer);
945
946     sz = sizeof(buffer);
947     r = MsiRecordGetString(hrec, 3, buffer, &sz);
948     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
949     ok(!lstrcmp(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
950
951     r = MsiCloseHandle(hrec);
952     ok(r == ERROR_SUCCESS, "failed to close record\n");
953
954     /* use a record that doesn't come from a view fetch */
955     hrec = MsiCreateRecord(3);
956     ok(hrec != 0, "MsiCreateRecord failed\n");
957
958     r = MsiRecordSetInteger(hrec, 1, 3);
959     ok(r == ERROR_SUCCESS, "failed to set integer\n");
960     r = MsiRecordSetString(hrec, 2, "jane");
961     ok(r == ERROR_SUCCESS, "failed to set string\n");
962     r = MsiRecordSetString(hrec, 3, "112358");
963     ok(r == ERROR_SUCCESS, "failed to set string\n");
964
965     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
966     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
967
968     r = MsiCloseHandle(hrec);
969     ok(r == ERROR_SUCCESS, "failed to close record\n");
970
971     /* use a record that doesn't come from a view fetch, primary key matches */
972     hrec = MsiCreateRecord(3);
973     ok(hrec != 0, "MsiCreateRecord failed\n");
974
975     r = MsiRecordSetInteger(hrec, 1, 1);
976     ok(r == ERROR_SUCCESS, "failed to set integer\n");
977     r = MsiRecordSetString(hrec, 2, "jane");
978     ok(r == ERROR_SUCCESS, "failed to set string\n");
979     r = MsiRecordSetString(hrec, 3, "112358");
980     ok(r == ERROR_SUCCESS, "failed to set string\n");
981
982     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
983     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
984
985     r = MsiCloseHandle(hrec);
986     ok(r == ERROR_SUCCESS, "failed to close record\n");
987
988     hrec = MsiCreateRecord(3);
989
990     r = MsiRecordSetInteger(hrec, 1, 2);
991     ok(r == ERROR_SUCCESS, "failed to set integer\n");
992     r = MsiRecordSetString(hrec, 2, "nick");
993     ok(r == ERROR_SUCCESS, "failed to set string\n");
994     r = MsiRecordSetString(hrec, 3, "141421");
995     ok(r == ERROR_SUCCESS, "failed to set string\n");
996
997     r = MsiViewExecute(hview, 0);
998     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
999     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
1000     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1001
1002     r = MsiCloseHandle(hrec);
1003     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1004     r = MsiViewClose(hview);
1005     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1006     r = MsiCloseHandle(hview);
1007     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1008
1009     query = "SELECT * FROM `phone` WHERE `id` = 1";
1010     r = MsiDatabaseOpenView(hdb, query, &hview);
1011     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1012     r = MsiViewExecute(hview, 0);
1013     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1014     r = MsiViewFetch(hview, &hrec);
1015     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1016
1017     /* change the id to match the second row */
1018     r = MsiRecordSetInteger(hrec, 1, 2);
1019     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1020     r = MsiRecordSetString(hrec, 2, "jerry");
1021     ok(r == ERROR_SUCCESS, "failed to set string\n");
1022
1023     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1024     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1025
1026     r = MsiCloseHandle(hrec);
1027     ok(r == ERROR_SUCCESS, "failed to close record\n");
1028     r = MsiViewClose(hview);
1029     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1030     r = MsiCloseHandle(hview);
1031     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1032
1033     /* broader search */
1034     query = "SELECT * FROM `phone` ORDER BY `id`";
1035     r = MsiDatabaseOpenView(hdb, query, &hview);
1036     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1037     r = MsiViewExecute(hview, 0);
1038     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1039     r = MsiViewFetch(hview, &hrec);
1040     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1041
1042     /* change the id to match the second row */
1043     r = MsiRecordSetInteger(hrec, 1, 2);
1044     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1045     r = MsiRecordSetString(hrec, 2, "jerry");
1046     ok(r == ERROR_SUCCESS, "failed to set string\n");
1047
1048     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1049     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1050
1051     r = MsiCloseHandle(hrec);
1052     ok(r == ERROR_SUCCESS, "failed to close record\n");
1053     r = MsiViewClose(hview);
1054     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1055     r = MsiCloseHandle(hview);
1056     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1057
1058     r = MsiCloseHandle( hdb );
1059     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1060 }
1061
1062 static MSIHANDLE create_db(void)
1063 {
1064     MSIHANDLE hdb = 0;
1065     UINT res;
1066
1067     DeleteFile(msifile);
1068
1069     /* create an empty database */
1070     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1071     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1072     if( res != ERROR_SUCCESS )
1073         return hdb;
1074
1075     res = MsiDatabaseCommit( hdb );
1076     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1077
1078     return hdb;
1079 }
1080
1081 static void test_getcolinfo(void)
1082 {
1083     MSIHANDLE hdb, hview = 0, rec = 0;
1084     UINT r;
1085     DWORD sz;
1086     char buffer[0x20];
1087
1088     /* create an empty db */
1089     hdb = create_db();
1090     ok( hdb, "failed to create db\n");
1091
1092     /* tables should be present */
1093     r = MsiDatabaseOpenView(hdb, "select * from _Tables", &hview);
1094     ok( r == ERROR_SUCCESS, "failed to open query\n");
1095
1096     r = MsiViewExecute(hview, 0);
1097     ok( r == ERROR_SUCCESS, "failed to execute query\n");
1098
1099     /* check that NAMES works */
1100     rec = 0;
1101     r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1102     ok( r == ERROR_SUCCESS, "failed to get names\n");
1103     sz = sizeof buffer;
1104     r = MsiRecordGetString(rec, 1, buffer, &sz );
1105     ok( r == ERROR_SUCCESS, "failed to get string\n");
1106     ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
1107     r = MsiCloseHandle( rec );
1108     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1109
1110     /* check that TYPES works */
1111     rec = 0;
1112     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1113     ok( r == ERROR_SUCCESS, "failed to get names\n");
1114     sz = sizeof buffer;
1115     r = MsiRecordGetString(rec, 1, buffer, &sz );
1116     ok( r == ERROR_SUCCESS, "failed to get string\n");
1117     ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
1118     r = MsiCloseHandle( rec );
1119     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1120
1121     /* check that invalid values fail */
1122     rec = 0;
1123     r = MsiViewGetColumnInfo( hview, 100, &rec );
1124     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1125     ok( rec == 0, "returned a record\n");
1126
1127     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1128     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1129
1130     r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1131     ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1132
1133     r = MsiViewClose(hview);
1134     ok( r == ERROR_SUCCESS, "failed to close view\n");
1135     r = MsiCloseHandle(hview);
1136     ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1137     r = MsiCloseHandle(hdb);
1138     ok( r == ERROR_SUCCESS, "failed to close database\n");
1139 }
1140
1141 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1142 {
1143     MSIHANDLE hview = 0, rec = 0;
1144     UINT r;
1145
1146     r = MsiDatabaseOpenView(hdb, query, &hview);
1147     if( r != ERROR_SUCCESS )
1148         return r;
1149
1150     r = MsiViewExecute(hview, 0);
1151     if( r == ERROR_SUCCESS )
1152     {
1153         MsiViewGetColumnInfo( hview, type, &rec );
1154     }
1155     MsiViewClose(hview);
1156     MsiCloseHandle(hview);
1157     return rec;
1158 }
1159
1160 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1161 {
1162     MSIHANDLE hview = 0, rec = 0;
1163     UINT r, type = 0;
1164     char query[0x100];
1165
1166     sprintf(query, "select * from `_Columns` where  `Table` = '%s'", table );
1167
1168     r = MsiDatabaseOpenView(hdb, query, &hview);
1169     if( r != ERROR_SUCCESS )
1170         return r;
1171
1172     r = MsiViewExecute(hview, 0);
1173     if( r == ERROR_SUCCESS )
1174     {
1175         while (1)
1176         {
1177             r = MsiViewFetch( hview, &rec );
1178             if( r != ERROR_SUCCESS)
1179                 break;
1180             r = MsiRecordGetInteger( rec, 2 );
1181             if (r == field)
1182                 type = MsiRecordGetInteger( rec, 4 );
1183             MsiCloseHandle( rec );
1184         }
1185     }
1186     MsiViewClose(hview);
1187     MsiCloseHandle(hview);
1188     return type;
1189 }
1190
1191 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
1192 {
1193     CHAR buffer[0x20];
1194     UINT r;
1195     DWORD sz;
1196
1197     sz = sizeof buffer;
1198     r = MsiRecordGetString( rec, field, buffer, &sz );
1199     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1200 }
1201
1202 static void test_viewgetcolumninfo(void)
1203 {
1204     MSIHANDLE hdb = 0, rec;
1205     UINT r;
1206
1207     hdb = create_db();
1208     ok( hdb, "failed to create db\n");
1209
1210     r = run_query( hdb, 0,
1211             "CREATE TABLE `Properties` "
1212             "( `Property` CHAR(255), "
1213             "  `Value` CHAR(1), "
1214             "  `Intvalue` INT, "
1215             "  `Integervalue` INTEGER, "
1216             "  `Shortvalue` SHORT, "
1217             "  `Longvalue` LONG, "
1218             "  `Longcharvalue` LONGCHAR "
1219             "  PRIMARY KEY `Property`)" );
1220     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1221
1222     /* check the column types */
1223     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1224     ok( rec, "failed to get column info record\n" );
1225
1226     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1227     ok( check_record( rec, 2, "S1"), "wrong record type\n");
1228     ok( check_record( rec, 3, "I2"), "wrong record type\n");
1229     ok( check_record( rec, 4, "I2"), "wrong record type\n");
1230     ok( check_record( rec, 5, "I2"), "wrong record type\n");
1231     ok( check_record( rec, 6, "I4"), "wrong record type\n");
1232     ok( check_record( rec, 7, "S0"), "wrong record type\n");
1233
1234     MsiCloseHandle( rec );
1235
1236     /* check the type in _Columns */
1237     ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1238     ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1239     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1240     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1241     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1242     ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1243     ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1244
1245     /* now try the names */
1246     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1247     ok( rec, "failed to get column info record\n" );
1248
1249     ok( check_record( rec, 1, "Property"), "wrong record type\n");
1250     ok( check_record( rec, 2, "Value"), "wrong record type\n");
1251     ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
1252     ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
1253     ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
1254     ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
1255     ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
1256
1257     MsiCloseHandle( rec );
1258
1259     r = run_query( hdb, 0,
1260             "CREATE TABLE `Binary` "
1261             "( `Name` CHAR(255), `Data` OBJECT  PRIMARY KEY `Name`)" );
1262     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1263
1264     /* check the column types */
1265     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1266     ok( rec, "failed to get column info record\n" );
1267
1268     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1269     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1270
1271     MsiCloseHandle( rec );
1272
1273     /* check the type in _Columns */
1274     ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1275     ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1276
1277     /* now try the names */
1278     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1279     ok( rec, "failed to get column info record\n" );
1280
1281     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1282     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1283     MsiCloseHandle( rec );
1284
1285     r = run_query( hdb, 0,
1286             "CREATE TABLE `UIText` "
1287             "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1288     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1289
1290     ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1291     ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1292
1293     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1294     ok( rec, "failed to get column info record\n" );
1295     ok( check_record( rec, 1, "Key"), "wrong record type\n");
1296     ok( check_record( rec, 2, "Text"), "wrong record type\n");
1297     MsiCloseHandle( rec );
1298
1299     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1300     ok( rec, "failed to get column info record\n" );
1301     ok( check_record( rec, 1, "s72"), "wrong record type\n");
1302     ok( check_record( rec, 2, "L255"), "wrong record type\n");
1303     MsiCloseHandle( rec );
1304
1305     MsiCloseHandle( hdb );
1306 }
1307
1308 static void test_msiexport(void)
1309 {
1310     MSIHANDLE hdb = 0, hview = 0;
1311     UINT r;
1312     const char *query;
1313     char path[MAX_PATH];
1314     const char file[] = "phone.txt";
1315     HANDLE handle;
1316     char buffer[0x100];
1317     DWORD length;
1318     const char expected[] =
1319         "id\tname\tnumber\r\n"
1320         "I2\tS32\tS32\r\n"
1321         "phone\tid\r\n"
1322         "1\tAbe\t8675309\r\n";
1323
1324     DeleteFile(msifile);
1325
1326     /* just MsiOpenDatabase should not create a file */
1327     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1328     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1329
1330     /* create a table */
1331     query = "CREATE TABLE `phone` ( "
1332             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1333             "PRIMARY KEY `id`)";
1334     r = MsiDatabaseOpenView(hdb, query, &hview);
1335     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1336     r = MsiViewExecute(hview, 0);
1337     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1338     r = MsiViewClose(hview);
1339     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1340     r = MsiCloseHandle(hview);
1341     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1342
1343     /* insert a value into it */
1344     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1345         "VALUES('1', 'Abe', '8675309')";
1346     r = MsiDatabaseOpenView(hdb, query, &hview);
1347     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1348     r = MsiViewExecute(hview, 0);
1349     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1350     r = MsiViewClose(hview);
1351     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1352     r = MsiCloseHandle(hview);
1353     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1354
1355     GetCurrentDirectory(MAX_PATH, path);
1356
1357     r = MsiDatabaseExport(hdb, "phone", path, file);
1358     ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1359
1360     MsiCloseHandle(hdb);
1361
1362     lstrcat(path, "\\");
1363     lstrcat(path, file);
1364
1365     /* check the data that was written */
1366     length = 0;
1367     memset(buffer, 0, sizeof buffer);
1368     handle = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1369     if (handle != INVALID_HANDLE_VALUE)
1370     {
1371         ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1372         CloseHandle(handle);
1373         DeleteFile(path);
1374     }
1375     else
1376         ok(0, "failed to open file %s\n", path);
1377
1378     ok( length == strlen(expected), "length of data wrong\n");
1379     ok( !lstrcmp(buffer, expected), "data doesn't match\n");
1380     DeleteFile(msifile);
1381 }
1382
1383 static void test_longstrings(void)
1384 {
1385     const char insert_query[] = 
1386         "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1387     char *str;
1388     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1389     DWORD len;
1390     UINT r;
1391     const DWORD STRING_LENGTH = 0x10005;
1392
1393     DeleteFile(msifile);
1394     /* just MsiOpenDatabase should not create a file */
1395     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1396     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1397
1398     /* create a table */
1399     r = try_query( hdb, 
1400         "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1401     ok(r == ERROR_SUCCESS, "query failed\n");
1402
1403     /* try a insert a very long string */
1404     str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
1405     len = strchr(insert_query, 'Z') - insert_query;
1406     strcpy(str, insert_query);
1407     memset(str+len, 'Z', STRING_LENGTH);
1408     strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1409     r = try_query( hdb, str );
1410     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1411
1412     HeapFree(GetProcessHeap(), 0, str);
1413
1414     MsiDatabaseCommit(hdb);
1415     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1416     MsiCloseHandle(hdb);
1417
1418     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
1419     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1420
1421     r = MsiDatabaseOpenView(hdb, "select * from `strings` where `id` = 1", &hview);
1422     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1423
1424     r = MsiViewExecute(hview, 0);
1425     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1426
1427     r = MsiViewFetch(hview, &hrec);
1428     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1429
1430     MsiViewClose(hview);
1431     MsiCloseHandle(hview);
1432
1433     r = MsiRecordGetString(hrec, 2, NULL, &len);
1434     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1435     ok(len == STRING_LENGTH, "string length wrong\n");
1436
1437     MsiCloseHandle(hrec);
1438     MsiCloseHandle(hdb);
1439     DeleteFile(msifile);
1440 }
1441
1442 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1443 {
1444     HANDLE file;
1445     DWORD written;
1446
1447     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1448     if (file == INVALID_HANDLE_VALUE)
1449         return;
1450
1451     WriteFile(file, data, strlen(data), &written, NULL);
1452     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1453
1454     if (size)
1455     {
1456         SetFilePointer(file, size, NULL, FILE_BEGIN);
1457         SetEndOfFile(file);
1458     }
1459
1460     CloseHandle(file);
1461 }
1462
1463 #define create_file(name) create_file_data(name, name, 0)
1464  
1465 static void test_streamtable(void)
1466 {
1467     MSIHANDLE hdb = 0, rec, view, hsi;
1468     char file[MAX_PATH];
1469     char buf[MAX_PATH];
1470     DWORD size;
1471     UINT r;
1472
1473     hdb = create_db();
1474     ok( hdb, "failed to create db\n");
1475
1476     r = run_query( hdb, 0,
1477             "CREATE TABLE `Properties` "
1478             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
1479     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1480
1481     r = run_query( hdb, 0,
1482             "INSERT INTO `Properties` "
1483             "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1484     ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1485
1486     r = MsiDatabaseCommit( hdb );
1487     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1488
1489     MsiCloseHandle( hdb );
1490
1491     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
1492     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1493
1494     /* check the column types */
1495     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1496     ok( rec, "failed to get column info record\n" );
1497
1498     ok( check_record( rec, 1, "s62"), "wrong record type\n");
1499     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1500
1501     MsiCloseHandle( rec );
1502
1503     /* now try the names */
1504     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1505     ok( rec, "failed to get column info record\n" );
1506
1507     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1508     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1509
1510     MsiCloseHandle( rec );
1511
1512     r = MsiDatabaseOpenView( hdb,
1513             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1514     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1515
1516     r = MsiViewExecute( view, 0 );
1517     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1518
1519     r = MsiViewFetch( view, &rec );
1520     ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1521
1522     MsiCloseHandle( rec );
1523     MsiViewClose( view );
1524     MsiCloseHandle( view );
1525
1526     /* create a summary information stream */
1527     r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1528     ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1529
1530     r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1531     ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1532
1533     r = MsiSummaryInfoPersist( hsi );
1534     ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1535
1536     MsiCloseHandle( hsi );
1537
1538     r = MsiDatabaseOpenView( hdb,
1539             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1540     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1541
1542     r = MsiViewExecute( view, 0 );
1543     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1544
1545     r = MsiViewFetch( view, &rec );
1546     ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1547
1548     MsiCloseHandle( rec );
1549     MsiViewClose( view );
1550     MsiCloseHandle( view );
1551
1552     /* insert a file into the _Streams table */
1553     create_file( "test.txt" );
1554
1555     rec = MsiCreateRecord( 2 );
1556     MsiRecordSetString( rec, 1, "data" );
1557
1558     r = MsiRecordSetStream( rec, 2, "test.txt" );
1559     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1560
1561     DeleteFile("test.txt");
1562
1563     r = MsiDatabaseOpenView( hdb,
1564             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1565     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1566
1567     r = MsiViewExecute( view, rec );
1568     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1569
1570     MsiCloseHandle( rec );
1571     MsiViewClose( view );
1572     MsiCloseHandle( view );
1573
1574     /* insert another one */
1575     create_file( "test1.txt" );
1576
1577     rec = MsiCreateRecord( 2 );
1578     MsiRecordSetString( rec, 1, "data1" );
1579
1580     r = MsiRecordSetStream( rec, 2, "test1.txt" );
1581     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1582
1583     DeleteFile("test1.txt");
1584
1585     r = MsiDatabaseOpenView( hdb,
1586             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1587     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1588
1589     r = MsiViewExecute( view, rec );
1590     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1591
1592     MsiCloseHandle( rec );
1593     MsiViewClose( view );
1594     MsiCloseHandle( view );
1595
1596     r = MsiDatabaseOpenView( hdb,
1597             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1598     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1599
1600     r = MsiViewExecute( view, 0 );
1601     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1602
1603     r = MsiViewFetch( view, &rec );
1604     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1605
1606     size = MAX_PATH;
1607     r = MsiRecordGetString( rec, 1, file, &size );
1608     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1609     ok( !lstrcmp(file, "data"), "Expected 'data', got %s\n", file);
1610
1611     size = MAX_PATH;
1612     memset(buf, 0, MAX_PATH);
1613     r = MsiRecordReadStream( rec, 2, buf, &size );
1614     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1615     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf);
1616
1617     MsiCloseHandle( rec );
1618     MsiViewClose( view );
1619     MsiCloseHandle( view );
1620
1621     r = MsiDatabaseOpenView( hdb,
1622             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1623     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1624
1625     r = MsiViewExecute( view, 0 );
1626     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1627
1628     r = MsiViewFetch( view, &rec );
1629     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1630
1631     size = MAX_PATH;
1632     r = MsiRecordGetString( rec, 1, file, &size );
1633     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1634     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1635
1636     size = MAX_PATH;
1637     memset(buf, 0, MAX_PATH);
1638     r = MsiRecordReadStream( rec, 2, buf, &size );
1639     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1640     ok( !lstrcmp(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
1641
1642     MsiCloseHandle( rec );
1643     MsiViewClose( view );
1644     MsiCloseHandle( view );
1645
1646     /* perform an update */
1647     create_file( "test2.txt" );
1648     rec = MsiCreateRecord( 1 );
1649
1650     r = MsiRecordSetStream( rec, 1, "test2.txt" );
1651     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1652
1653     DeleteFile("test2.txt");
1654
1655     r = MsiDatabaseOpenView( hdb,
1656             "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1657     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1658
1659     r = MsiViewExecute( view, rec );
1660     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1661
1662     MsiCloseHandle( rec );
1663     MsiViewClose( view );
1664     MsiCloseHandle( view );
1665
1666     r = MsiDatabaseOpenView( hdb,
1667             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1668     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1669
1670     r = MsiViewExecute( view, 0 );
1671     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1672
1673     r = MsiViewFetch( view, &rec );
1674     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1675
1676     size = MAX_PATH;
1677     r = MsiRecordGetString( rec, 1, file, &size );
1678     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1679     ok( !lstrcmp(file, "data1"), "Expected 'data1', got %s\n", file);
1680
1681     size = MAX_PATH;
1682     memset(buf, 0, MAX_PATH);
1683     r = MsiRecordReadStream( rec, 2, buf, &size );
1684     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1685     todo_wine ok( !lstrcmp(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
1686
1687     MsiCloseHandle( rec );
1688     MsiViewClose( view );
1689     MsiCloseHandle( view );
1690     MsiCloseHandle( hdb );
1691     DeleteFile(msifile);
1692 }
1693
1694 static void test_binary(void)
1695 {
1696     MSIHANDLE hdb = 0, rec;
1697     char file[MAX_PATH];
1698     char buf[MAX_PATH];
1699     DWORD size;
1700     LPCSTR query;
1701     UINT r;
1702
1703     /* insert a file into the Binary table */
1704     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
1705     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1706
1707     query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
1708     r = run_query( hdb, 0, query );
1709     ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1710
1711     create_file( "test.txt" );
1712     rec = MsiCreateRecord( 1 );
1713     r = MsiRecordSetStream( rec, 1, "test.txt" );
1714     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1715     DeleteFile( "test.txt" );
1716
1717     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1718     r = run_query( hdb, rec, query );
1719     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1720
1721     r = MsiCloseHandle( rec );
1722     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1723
1724     r = MsiDatabaseCommit( hdb );
1725     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1726
1727     r = MsiCloseHandle( hdb );
1728     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1729
1730     /* read file from the Stream table */
1731     r = MsiOpenDatabase( msifile, MSIDBOPEN_READONLY, &hdb );
1732     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1733
1734     query = "SELECT * FROM `_Streams`";
1735     r = do_query( hdb, query, &rec );
1736     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1737
1738     size = MAX_PATH;
1739     r = MsiRecordGetString( rec, 1, file, &size );
1740     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1741     ok( !lstrcmp(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1742
1743     size = MAX_PATH;
1744     memset( buf, 0, MAX_PATH );
1745     r = MsiRecordReadStream( rec, 2, buf, &size );
1746     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1747     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1748
1749     r = MsiCloseHandle( rec );
1750     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1751
1752     /* read file from the Binary table */
1753     query = "SELECT * FROM `Binary`";
1754     r = do_query( hdb, query, &rec );
1755     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1756
1757     size = MAX_PATH;
1758     r = MsiRecordGetString( rec, 1, file, &size );
1759     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1760     ok( !lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file );
1761
1762     size = MAX_PATH;
1763     memset( buf, 0, MAX_PATH );
1764     r = MsiRecordReadStream( rec, 3, buf, &size );
1765     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1766     ok( !lstrcmp(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1767
1768     r = MsiCloseHandle( rec );
1769     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1770
1771     r = MsiCloseHandle( hdb );
1772     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1773
1774     DeleteFile( msifile );
1775 }
1776
1777 static void test_where_not_in_selected(void)
1778 {
1779     MSIHANDLE hdb = 0, rec, view;
1780     LPCSTR query;
1781     UINT r;
1782
1783     hdb = create_db();
1784     ok( hdb, "failed to create db\n");
1785
1786     r = run_query(hdb, 0,
1787             "CREATE TABLE `IESTable` ("
1788             "`Action` CHAR(64), "
1789             "`Condition` CHAR(64), "
1790             "`Sequence` LONG PRIMARY KEY `Sequence`)");
1791     ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1792
1793     r = run_query(hdb, 0,
1794             "CREATE TABLE `CATable` ("
1795             "`Action` CHAR(64), "
1796             "`Type` LONG PRIMARY KEY `Type`)");
1797     ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1798
1799     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1800             "( `Action`, `Condition`, `Sequence`) "
1801             "VALUES ( 'clean', 'cond4', 4)");
1802     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1803
1804     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1805             "( `Action`, `Condition`, `Sequence`) "
1806             "VALUES ( 'depends', 'cond1', 1)");
1807     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1808
1809     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1810             "( `Action`, `Condition`, `Sequence`) "
1811             "VALUES ( 'build', 'cond2', 2)");
1812     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1813
1814     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1815             "( `Action`, `Condition`, `Sequence`) "
1816             "VALUES ( 'build2', 'cond6', 6)");
1817     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1818
1819     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1820             "( `Action`, `Condition`, `Sequence`) "
1821             "VALUES ( 'build', 'cond3', 3)");
1822     ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1823
1824     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1825             "( `Action`, `Type` ) "
1826             "VALUES ( 'build', 32)");
1827     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1828
1829     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1830             "( `Action`, `Type` ) "
1831             "VALUES ( 'depends', 64)");
1832     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1833
1834     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1835             "( `Action`, `Type` ) "
1836             "VALUES ( 'clean', 63)");
1837     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1838
1839     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1840             "( `Action`, `Type` ) "
1841             "VALUES ( 'build2', 34)");
1842     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1843     query = "Select IESTable.Condition from CATable, IESTable where "
1844             "CATable.Action = IESTable.Action and CATable.Type = 32";
1845     r = MsiDatabaseOpenView(hdb, query, &view);
1846     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1847
1848     r = MsiViewExecute(view, 0);
1849     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1850
1851     r = MsiViewFetch(view, &rec);
1852     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1853
1854     ok( check_record( rec, 1, "cond2"), "wrong condition\n");
1855
1856     MsiCloseHandle( rec );
1857     r = MsiViewFetch(view, &rec);
1858     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1859
1860     ok( check_record( rec, 1, "cond3"), "wrong condition\n");
1861
1862     MsiCloseHandle( rec );
1863     MsiViewClose(view);
1864     MsiCloseHandle(view);
1865
1866     MsiCloseHandle( hdb );
1867     DeleteFile(msifile);
1868
1869 }
1870
1871
1872 static void test_where(void)
1873 {
1874     MSIHANDLE hdb = 0, rec, view;
1875     LPCSTR query;
1876     UINT r;
1877     DWORD size;
1878     CHAR buf[MAX_PATH];
1879     UINT count;
1880
1881     hdb = create_db();
1882     ok( hdb, "failed to create db\n");
1883
1884     r = run_query( hdb, 0,
1885             "CREATE TABLE `Media` ("
1886             "`DiskId` SHORT NOT NULL, "
1887             "`LastSequence` LONG, "
1888             "`DiskPrompt` CHAR(64) LOCALIZABLE, "
1889             "`Cabinet` CHAR(255), "
1890             "`VolumeLabel` CHAR(32), "
1891             "`Source` CHAR(72) "
1892             "PRIMARY KEY `DiskId`)" );
1893     ok( r == S_OK, "cannot create Media table: %d\n", r );
1894
1895     r = run_query( hdb, 0, "INSERT INTO `Media` "
1896             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1897             "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
1898     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1899
1900     r = run_query( hdb, 0, "INSERT INTO `Media` "
1901             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1902             "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
1903     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1904
1905     r = run_query( hdb, 0, "INSERT INTO `Media` "
1906             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1907             "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
1908     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1909
1910     query = "SELECT * FROM `Media`";
1911     r = do_query(hdb, query, &rec);
1912     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1913     ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
1914     MsiCloseHandle( rec );
1915
1916     query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
1917     r = do_query(hdb, query, &rec);
1918     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1919     ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
1920
1921     r = MsiRecordGetInteger(rec, 1);
1922     ok( 2 == r, "field wrong\n");
1923     r = MsiRecordGetInteger(rec, 2);
1924     ok( 1 == r, "field wrong\n");
1925     MsiCloseHandle( rec );
1926
1927     query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
1928     r = MsiDatabaseOpenView(hdb, query, &view);
1929     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1930
1931     r = MsiViewExecute(view, 0);
1932     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1933
1934     r = MsiViewFetch(view, &rec);
1935     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1936
1937     count = MsiRecordGetFieldCount( rec );
1938     ok( count == 1, "Expected 1 record fields, got %d\n", count );
1939
1940     size = MAX_PATH;
1941     r = MsiRecordGetString( rec, 1, buf, &size );
1942     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
1943     ok( !lstrcmp( buf, "2" ),
1944         "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
1945     MsiCloseHandle( rec );
1946
1947     r = MsiViewFetch(view, &rec);
1948     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1949
1950     size = MAX_PATH;
1951     r = MsiRecordGetString( rec, 1, buf, &size );
1952     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
1953     ok( !lstrcmp( buf, "3" ),
1954         "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
1955     MsiCloseHandle( rec );
1956
1957     r = MsiViewFetch(view, &rec);
1958     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
1959
1960     MsiViewClose(view);
1961     MsiCloseHandle(view);
1962
1963     MsiCloseHandle( rec );
1964
1965     rec = 0;
1966     query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
1967     r = do_query(hdb, query, &rec);
1968     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
1969     MsiCloseHandle( rec );
1970
1971     rec = 0;
1972     query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
1973     r = do_query(hdb, query, &rec);
1974     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
1975     MsiCloseHandle( rec );
1976
1977     rec = 0;
1978     query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
1979     r = do_query(hdb, query, &rec);
1980     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
1981     MsiCloseHandle( rec );
1982
1983     rec = 0;
1984     query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
1985     r = do_query(hdb, query, &rec);
1986     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
1987     MsiCloseHandle( rec );
1988
1989     rec = 0;
1990     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
1991     r = do_query(hdb, query, &rec);
1992     ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
1993     MsiCloseHandle( rec );
1994
1995     rec = MsiCreateRecord(1);
1996     MsiRecordSetString(rec, 1, "");
1997
1998     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
1999     r = MsiDatabaseOpenView(hdb, query, &view);
2000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2001     r = MsiViewExecute(view, rec);
2002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2003
2004     MsiCloseHandle(rec);
2005
2006     r = MsiViewFetch(view, &rec);
2007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2008
2009     MsiCloseHandle(rec);
2010     MsiViewClose(view);
2011     MsiCloseHandle(view);
2012
2013     MsiCloseHandle( hdb );
2014     DeleteFile(msifile);
2015 }
2016
2017 static CHAR CURR_DIR[MAX_PATH];
2018
2019 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
2020                                 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
2021                                 "TestTable\tFirstPrimaryColumn\n"
2022                                 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
2023
2024 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
2025                                   "s255\ts255\n"
2026                                   "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
2027                                   "papaya\tleaf\n"
2028                                   "papaya\tflower\n";
2029
2030 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
2031                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2032                                 "Table\tA\r\n"
2033                                 "a\tb\tc\td\te\tf\n"
2034                                 "g\th\ti\t\rj\tk\tl\r\n";
2035
2036 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
2037                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2038                                 "Table2\tA\r\n"
2039                                 "a\tb\tc\td\te\tf\n"
2040                                 "g\th\ti\tj\tk\tl\r\n";
2041
2042 static const CHAR suminfo[] = "PropertyId\tValue\n"
2043                               "i2\tl255\n"
2044                               "_SummaryInformation\tPropertyId\n"
2045                               "1\t1252\n"
2046                               "2\tInstaller Database\n"
2047                               "3\tInstaller description\n"
2048                               "4\tWineHQ\n"
2049                               "5\tInstaller\n"
2050                               "6\tInstaller comments\n"
2051                               "7\tIntel;1033,2057\n"
2052                               "9\t{12345678-1234-1234-1234-123456789012}\n"
2053                               "12\t2009/04/12 15:46:11\n"
2054                               "13\t2009/04/12 15:46:11\n"
2055                               "14\t200\n"
2056                               "15\t2\n"
2057                               "18\tVim\n"
2058                               "19\t2\n";
2059
2060 static void write_file(const CHAR *filename, const char *data, int data_size)
2061 {
2062     DWORD size;
2063
2064     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
2065                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2066
2067     WriteFile(hf, data, data_size, &size, NULL);
2068     CloseHandle(hf);
2069 }
2070
2071 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2072 {
2073     UINT r;
2074
2075     write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
2076     r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2077     DeleteFileA("temp_file");
2078
2079     return r;
2080 }
2081
2082 static void test_suminfo_import(void)
2083 {
2084     MSIHANDLE hdb, hsi, view = 0;
2085     LPCSTR query;
2086     UINT r, count, size, type;
2087     char str_value[50];
2088     INT int_value;
2089     FILETIME ft_value;
2090
2091     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2092
2093     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2095
2096     r = add_table_to_db(hdb, suminfo);
2097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2098
2099     /* _SummaryInformation is not imported as a regular table... */
2100
2101     query = "SELECT * FROM `_SummaryInformation`";
2102     r = MsiDatabaseOpenViewA(hdb, query, &view);
2103     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2104     MsiCloseHandle(view);
2105
2106     /* ...its data is added to the special summary information stream */
2107
2108     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2110
2111     r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2113     ok(count == 14, "Expected 14, got %u\n", count);
2114
2115     r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2117     ok(type ==  VT_I2, "Expected VT_I2, got %u\n", type);
2118     ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2119
2120     size = sizeof(str_value);
2121     r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2123     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2124     ok(size == 18, "Expected 18, got %u\n", size);
2125     ok(!strcmp(str_value, "Installer Database"),
2126        "Expected \"Installer Database\", got %s\n", str_value);
2127
2128     size = sizeof(str_value);
2129     r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2131     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2132     ok(!strcmp(str_value, "Installer description"),
2133        "Expected \"Installer description\", got %s\n", str_value);
2134
2135     size = sizeof(str_value);
2136     r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2138     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2139     ok(!strcmp(str_value, "WineHQ"),
2140        "Expected \"WineHQ\", got %s\n", str_value);
2141
2142     size = sizeof(str_value);
2143     r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2144     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2145     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2146     ok(!strcmp(str_value, "Installer"),
2147        "Expected \"Installer\", got %s\n", str_value);
2148
2149     size = sizeof(str_value);
2150     r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2152     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2153     ok(!strcmp(str_value, "Installer comments"),
2154        "Expected \"Installer comments\", got %s\n", str_value);
2155
2156     size = sizeof(str_value);
2157     r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2159     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2160     ok(!strcmp(str_value, "Intel;1033,2057"),
2161        "Expected \"Intel;1033,2057\", got %s\n", str_value);
2162
2163     size = sizeof(str_value);
2164     r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2165     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2166     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2167     ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2168        "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2169
2170     r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2172     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2173
2174     r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2176     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2177
2178     r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2180     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2181     ok(int_value == 200, "Expected 200, got %d\n", int_value);
2182
2183     r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2185     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2186     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2187
2188     r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2190     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2191     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2192
2193     size = sizeof(str_value);
2194     r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2196     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2197     ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2198
2199     MsiCloseHandle(hsi);
2200     MsiCloseHandle(hdb);
2201     DeleteFileA(msifile);
2202 }
2203
2204 static void test_msiimport(void)
2205 {
2206     MSIHANDLE hdb, view, rec;
2207     LPCSTR query;
2208     UINT r, count;
2209     signed int i;
2210
2211     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2212
2213     r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
2214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2215
2216     r = add_table_to_db(hdb, test_data);
2217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2218
2219     r = add_table_to_db(hdb, two_primary);
2220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2221
2222     r = add_table_to_db(hdb, endlines1);
2223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2224
2225     r = add_table_to_db(hdb, endlines2);
2226     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2227
2228     query = "SELECT * FROM `TestTable`";
2229     r = MsiDatabaseOpenView(hdb, query, &view);
2230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2231
2232     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2234     count = MsiRecordGetFieldCount(rec);
2235     ok(count == 9, "Expected 9, got %d\n", count);
2236     ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2237     ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2238     ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2239     ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2240     ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2241     ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2242     ok(check_record(rec, 7, "String"), "Expected String\n");
2243     ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2244     ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2245     MsiCloseHandle(rec);
2246
2247     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2249     count = MsiRecordGetFieldCount(rec);
2250     ok(count == 9, "Expected 9, got %d\n", count);
2251     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2252     ok(check_record(rec, 2, "i2"), "Expected i2\n");
2253     ok(check_record(rec, 3, "i2"), "Expected i2\n");
2254     ok(check_record(rec, 4, "I2"), "Expected I2\n");
2255     ok(check_record(rec, 5, "i4"), "Expected i4\n");
2256     ok(check_record(rec, 6, "I4"), "Expected I4\n");
2257     ok(check_record(rec, 7, "S255"), "Expected S255\n");
2258     ok(check_record(rec, 8, "S0"), "Expected S0\n");
2259     ok(check_record(rec, 9, "s0"), "Expected s0\n");
2260     MsiCloseHandle(rec);
2261
2262     query = "SELECT * FROM `TestTable`";
2263     r = do_query(hdb, query, &rec);
2264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2265     ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2266     ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2267     ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2268     ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2269
2270     i = MsiRecordGetInteger(rec, 2);
2271     ok(i == 5, "Expected 5, got %d\n", i);
2272
2273     i = MsiRecordGetInteger(rec, 3);
2274     ok(i == 2, "Expected 2, got %d\n", i);
2275
2276     i = MsiRecordGetInteger(rec, 4);
2277     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2278
2279     i = MsiRecordGetInteger(rec, 5);
2280     ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2281
2282     i = MsiRecordGetInteger(rec, 6);
2283     ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2284
2285     MsiCloseHandle(rec);
2286     MsiViewClose(view);
2287     MsiCloseHandle(view);
2288
2289     query = "SELECT * FROM `TwoPrimary`";
2290     r = MsiDatabaseOpenView(hdb, query, &view);
2291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2292
2293     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2295     count = MsiRecordGetFieldCount(rec);
2296     ok(count == 2, "Expected 2, got %d\n", count);
2297     ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2298     ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2299
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 == 2, "Expected 2, got %d\n", count);
2306     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2307     ok(check_record(rec, 2, "s255"), "Expected s255\n");
2308     MsiCloseHandle(rec);
2309
2310     r = MsiViewExecute(view, 0);
2311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2312
2313     r = MsiViewFetch(view, &rec);
2314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2315
2316     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2317     ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2318
2319     MsiCloseHandle(rec);
2320
2321     r = MsiViewFetch(view, &rec);
2322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2323
2324     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2325     ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2326
2327     MsiCloseHandle(rec);
2328
2329     r = MsiViewFetch(view, &rec);
2330     ok(r == ERROR_NO_MORE_ITEMS,
2331        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2332
2333     r = MsiViewClose(view);
2334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2335
2336     MsiCloseHandle(view);
2337
2338     query = "SELECT * FROM `Table`";
2339     r = MsiDatabaseOpenView(hdb, query, &view);
2340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2341
2342     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2344     count = MsiRecordGetFieldCount(rec);
2345     ok(count == 6, "Expected 6, got %d\n", count);
2346     ok(check_record(rec, 1, "A"), "Expected A\n");
2347     ok(check_record(rec, 2, "B"), "Expected B\n");
2348     ok(check_record(rec, 3, "C"), "Expected C\n");
2349     ok(check_record(rec, 4, "D"), "Expected D\n");
2350     ok(check_record(rec, 5, "E"), "Expected E\n");
2351     ok(check_record(rec, 6, "F"), "Expected F\n");
2352     MsiCloseHandle(rec);
2353
2354     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2356     count = MsiRecordGetFieldCount(rec);
2357     ok(count == 6, "Expected 6, got %d\n", count);
2358     ok(check_record(rec, 1, "s72"), "Expected s72\n");
2359     ok(check_record(rec, 2, "s72"), "Expected s72\n");
2360     ok(check_record(rec, 3, "s72"), "Expected s72\n");
2361     ok(check_record(rec, 4, "s72"), "Expected s72\n");
2362     ok(check_record(rec, 5, "s72"), "Expected s72\n");
2363     ok(check_record(rec, 6, "s72"), "Expected s72\n");
2364     MsiCloseHandle(rec);
2365
2366     MsiViewClose(view);
2367     MsiCloseHandle(view);
2368
2369     query = "SELECT * FROM `Table`";
2370     r = MsiDatabaseOpenView(hdb, query, &view);
2371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2372
2373     r = MsiViewExecute(view, 0);
2374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2375
2376     r = MsiViewFetch(view, &rec);
2377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2378     ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2379     ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2380     ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2381     ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2382     ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2383     ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2384
2385     MsiCloseHandle(rec);
2386
2387     r = MsiViewFetch(view, &rec);
2388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2389     ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2390     ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2391     ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2392     ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2393     ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2394     ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2395
2396     MsiCloseHandle(rec);
2397
2398     r = MsiViewFetch(view, &rec);
2399     ok(r == ERROR_NO_MORE_ITEMS,
2400        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2401
2402     MsiViewClose(view);
2403     MsiCloseHandle(view);
2404     MsiCloseHandle(hdb);
2405     DeleteFileA(msifile);
2406 }
2407
2408 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2409                                      "s72\tV0\r\n"
2410                                      "Binary\tName\r\n"
2411                                      "filename1\tfilename1.ibd\r\n";
2412
2413 static void test_binary_import(void)
2414 {
2415     MSIHANDLE hdb = 0, rec;
2416     char file[MAX_PATH];
2417     char buf[MAX_PATH];
2418     char path[MAX_PATH];
2419     DWORD size;
2420     LPCSTR query;
2421     UINT r;
2422
2423     /* create files to import */
2424     write_file("bin_import.idt", bin_import_dat,
2425           (sizeof(bin_import_dat) - 1) * sizeof(char));
2426     CreateDirectory("bin_import", NULL);
2427     create_file_data("bin_import/filename1.ibd", "just some words", 15);
2428
2429     /* import files into database */
2430     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
2431     ok( r == ERROR_SUCCESS , "Failed to open database\n");
2432
2433     GetCurrentDirectory(MAX_PATH, path);
2434     r = MsiDatabaseImport(hdb, path, "bin_import.idt");
2435     ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2436
2437     /* read file from the Binary table */
2438     query = "SELECT * FROM `Binary`";
2439     r = do_query(hdb, query, &rec);
2440     ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2441
2442     size = MAX_PATH;
2443     r = MsiRecordGetString(rec, 1, file, &size);
2444     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2445     ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file);
2446
2447     size = MAX_PATH;
2448     memset(buf, 0, MAX_PATH);
2449     r = MsiRecordReadStream(rec, 2, buf, &size);
2450     ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2451     ok(!lstrcmp(buf, "just some words"),
2452         "Expected 'just some words', got %s\n", buf);
2453
2454     r = MsiCloseHandle(rec);
2455     ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2456
2457     r = MsiCloseHandle(hdb);
2458     ok(r == ERROR_SUCCESS , "Failed to close database\n");
2459
2460     DeleteFile("bin_import/filename1.ibd");
2461     RemoveDirectory("bin_import");
2462     DeleteFile("bin_import.idt");
2463 }
2464
2465 static void test_markers(void)
2466 {
2467     MSIHANDLE hdb, rec;
2468     LPCSTR query;
2469     UINT r;
2470
2471     hdb = create_db();
2472     ok( hdb, "failed to create db\n");
2473
2474     rec = MsiCreateRecord(3);
2475     MsiRecordSetString(rec, 1, "Table");
2476     MsiRecordSetString(rec, 2, "Apples");
2477     MsiRecordSetString(rec, 3, "Oranges");
2478
2479     /* try a legit create */
2480     query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2481     r = run_query(hdb, 0, query);
2482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2483     MsiCloseHandle(rec);
2484
2485     /* try table name as marker */
2486     rec = MsiCreateRecord(1);
2487     MsiRecordSetString(rec, 1, "Fable");
2488     query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2489     r = run_query(hdb, rec, query);
2490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2491
2492     /* verify that we just created a table called '?', not 'Fable' */
2493     r = try_query(hdb, "SELECT * from `Fable`");
2494     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2495
2496     r = try_query(hdb, "SELECT * from `?`");
2497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2498
2499     /* try table name as marker without backticks */
2500     MsiRecordSetString(rec, 1, "Mable");
2501     query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2502     r = run_query(hdb, rec, query);
2503     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2504
2505     /* try one column name as marker */
2506     MsiRecordSetString(rec, 1, "One");
2507     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2508     r = run_query(hdb, rec, query);
2509     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2510     MsiCloseHandle(rec);
2511
2512     /* try column names as markers */
2513     rec = MsiCreateRecord(2);
2514     MsiRecordSetString(rec, 1, "One");
2515     MsiRecordSetString(rec, 2, "Two");
2516     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2517     r = run_query(hdb, rec, query);
2518     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2519     MsiCloseHandle(rec);
2520
2521     /* try names with backticks */
2522     rec = MsiCreateRecord(3);
2523     MsiRecordSetString(rec, 1, "One");
2524     MsiRecordSetString(rec, 2, "Two");
2525     MsiRecordSetString(rec, 3, "One");
2526     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2527     r = run_query(hdb, rec, query);
2528     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2529
2530     /* try names with backticks, minus definitions */
2531     query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2532     r = run_query(hdb, rec, query);
2533     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2534
2535     /* try names without backticks */
2536     query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2537     r = run_query(hdb, rec, query);
2538     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2539     MsiCloseHandle(rec);
2540
2541     /* try one long marker */
2542     rec = MsiCreateRecord(1);
2543     MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2544     query = "CREATE TABLE `Mable` ( ? )";
2545     r = run_query(hdb, rec, query);
2546     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2547     MsiCloseHandle(rec);
2548
2549     /* try all names as markers */
2550     rec = MsiCreateRecord(4);
2551     MsiRecordSetString(rec, 1, "Mable");
2552     MsiRecordSetString(rec, 2, "One");
2553     MsiRecordSetString(rec, 3, "Two");
2554     MsiRecordSetString(rec, 4, "One");
2555     query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2556     r = run_query(hdb, rec, query);
2557     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2558     MsiCloseHandle(rec);
2559
2560     /* try a legit insert */
2561     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2562     r = run_query(hdb, 0, query);
2563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2564
2565     r = try_query(hdb, "SELECT * from `Table`");
2566     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2567
2568     /* try values as markers */
2569     rec = MsiCreateRecord(2);
2570     MsiRecordSetInteger(rec, 1, 4);
2571     MsiRecordSetString(rec, 2, "hi");
2572     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2573     r = run_query(hdb, rec, query);
2574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2575     MsiCloseHandle(rec);
2576
2577     /* try column names and values as markers */
2578     rec = MsiCreateRecord(4);
2579     MsiRecordSetString(rec, 1, "One");
2580     MsiRecordSetString(rec, 2, "Two");
2581     MsiRecordSetInteger(rec, 3, 5);
2582     MsiRecordSetString(rec, 4, "hi");
2583     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2584     r = run_query(hdb, rec, query);
2585     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2586     MsiCloseHandle(rec);
2587
2588     /* try column names as markers */
2589     rec = MsiCreateRecord(2);
2590     MsiRecordSetString(rec, 1, "One");
2591     MsiRecordSetString(rec, 2, "Two");
2592     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2593     r = run_query(hdb, rec, query);
2594     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2595     MsiCloseHandle(rec);
2596
2597     /* try table name as a marker */
2598     rec = MsiCreateRecord(1);
2599     MsiRecordSetString(rec, 1, "Table");
2600     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2601     r = run_query(hdb, rec, query);
2602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2603     MsiCloseHandle(rec);
2604
2605     /* try table name and values as markers */
2606     rec = MsiCreateRecord(3);
2607     MsiRecordSetString(rec, 1, "Table");
2608     MsiRecordSetInteger(rec, 2, 10);
2609     MsiRecordSetString(rec, 3, "haha");
2610     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2611     r = run_query(hdb, rec, query);
2612     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2613     MsiCloseHandle(rec);
2614
2615     /* try all markers */
2616     rec = MsiCreateRecord(5);
2617     MsiRecordSetString(rec, 1, "Table");
2618     MsiRecordSetString(rec, 1, "One");
2619     MsiRecordSetString(rec, 1, "Two");
2620     MsiRecordSetInteger(rec, 2, 10);
2621     MsiRecordSetString(rec, 3, "haha");
2622     query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2623     r = run_query(hdb, rec, query);
2624     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2625     MsiCloseHandle(rec);
2626
2627     /* insert an integer as a string */
2628     rec = MsiCreateRecord(2);
2629     MsiRecordSetString(rec, 1, "11");
2630     MsiRecordSetString(rec, 2, "hi");
2631     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2632     r = run_query(hdb, rec, query);
2633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2634     MsiCloseHandle(rec);
2635
2636     /* leave off the '' for the string */
2637     rec = MsiCreateRecord(2);
2638     MsiRecordSetInteger(rec, 1, 12);
2639     MsiRecordSetString(rec, 2, "hi");
2640     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2641     r = run_query(hdb, rec, query);
2642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2643     MsiCloseHandle(rec);
2644
2645     MsiCloseHandle(hdb);
2646     DeleteFileA(msifile);
2647 }
2648
2649 #define MY_NVIEWS 4000    /* Largest installer I've seen uses < 2k */
2650 static void test_handle_limit(void)
2651 {
2652     int i;
2653     MSIHANDLE hdb;
2654     MSIHANDLE hviews[MY_NVIEWS];
2655     UINT r;
2656
2657     /* create an empty db */
2658     hdb = create_db();
2659     ok( hdb, "failed to create db\n");
2660
2661     memset(hviews, 0, sizeof(hviews));
2662
2663     for (i=0; i<MY_NVIEWS; i++) {
2664         static char szQueryBuf[256] = "SELECT * from `_Tables`";
2665         hviews[i] = 0xdeadbeeb;
2666         r = MsiDatabaseOpenView(hdb, szQueryBuf, &hviews[i]);
2667         if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 
2668             hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2669             break;
2670     }
2671
2672     ok( i == MY_NVIEWS, "problem opening views\n");
2673
2674     for (i=0; i<MY_NVIEWS; i++) {
2675         if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2676             MsiViewClose(hviews[i]);
2677             r = MsiCloseHandle(hviews[i]);
2678             if (r != ERROR_SUCCESS)
2679                 break;
2680         }
2681     }
2682
2683     ok( i == MY_NVIEWS, "problem closing views\n");
2684
2685     r = MsiCloseHandle(hdb);
2686     ok( r == ERROR_SUCCESS, "failed to close database\n");
2687 }
2688
2689 static void generate_transform(void)
2690 {
2691     MSIHANDLE hdb1, hdb2, hrec;
2692     LPCSTR query;
2693     UINT r;
2694
2695     /* start with two identical databases */
2696     CopyFile(msifile2, msifile, FALSE);
2697
2698     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb1 );
2699     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2700
2701     r = MsiDatabaseCommit( hdb1 );
2702     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2703
2704     r = MsiOpenDatabase(msifile2, MSIDBOPEN_READONLY, &hdb2 );
2705     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2706
2707     /* the transform between two identical database should be empty */
2708     r = MsiDatabaseGenerateTransform(hdb1, hdb2, NULL, 0, 0);
2709     todo_wine {
2710     ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2711     }
2712
2713     query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2714     r = run_query(hdb1, 0, query);
2715     ok(r == ERROR_SUCCESS, "failed to add table\n");
2716
2717     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2718     r = run_query(hdb1, 0, query);
2719     ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2720
2721     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2722     r = run_query(hdb1, 0, query);
2723     ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2724
2725     query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2726     r = run_query(hdb1, 0, query);
2727     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2728
2729     query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2730     r = run_query(hdb1, 0, query);
2731     ok(r == ERROR_SUCCESS, "failed to delete row\n");
2732
2733     hrec = MsiCreateRecord(2);
2734     r = MsiRecordSetInteger(hrec, 1, 1);
2735     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2736
2737     write_file("testdata.bin", "naengmyon", 9);
2738     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
2739     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2740
2741     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2742     r = run_query(hdb1, hrec, query);
2743     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2744
2745     MsiCloseHandle(hrec);
2746
2747     query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2748     r = run_query(hdb1, 0, query);
2749     ok(r == ERROR_SUCCESS, "failed to add column\n");
2750
2751     query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2752     r = run_query(hdb1, 0, query);
2753     ok(r == ERROR_SUCCESS, "failed to add column\n");
2754
2755     query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2756     r = run_query(hdb1, 0, query);
2757     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2758
2759     query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2760             "`Value` CHAR(0) PRIMARY KEY `Property`)";
2761     r = run_query(hdb1, 0, query);
2762     ok(r == ERROR_SUCCESS, "failed to add property table\n");
2763
2764     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2765     r = run_query(hdb1, 0, query);
2766     ok(r == ERROR_SUCCESS, "failed to add property\n");
2767
2768     /* database needs to be committed */
2769     MsiDatabaseCommit(hdb1);
2770
2771     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2772     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2773
2774     MsiCloseHandle( hdb1 );
2775     MsiCloseHandle( hdb2 );
2776
2777     DeleteFile("testdata.bin");
2778 }
2779
2780 /* data for generating a transform */
2781
2782 /* tables transform names - encoded as they would be in an msi database file */
2783 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2784 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2785 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2786 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2787 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2788 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2789 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2790 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2791 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2792
2793 /* data in each table */
2794 static const WCHAR data1[] = { /* AAR */
2795     0x0201, 0x0008, 0x8001,  /* 0x0201 = add row (1), two shorts */
2796     0x0201, 0x0009, 0x8002,
2797 };
2798 static const WCHAR data2[] = { /* _Columns */
2799     0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2800     0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2801     0x0401, 0x0005, 0x0000, 0x0006, 0xbdff,  /* 0x0401 = add row (1), 4 shorts */
2802     0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2803     0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2804     0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2805 };
2806 static const WCHAR data3[] = { /* _Tables */
2807     0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2808     0x0101, 0x000a,
2809 };
2810 static const char data4[] = /* _StringData */
2811     "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval";  /* all the strings squashed together */
2812 static const WCHAR data5[] = { /* _StringPool */
2813 /*  len, refs */
2814     0,   0,    /* string 0 ''    */
2815     3,   2,    /* string 1 'MOO' */
2816     3,   1,    /* string 2 'COW' */
2817     3,   1,    /* string 3 'PIG' */
2818     1,   1,    /* string 4 'c'   */
2819     3,   3,    /* string 5 'AAR' */
2820     3,   1,    /* string 6 'CAR' */
2821     3,   1,    /* string 7 'BAR' */
2822     2,   1,    /* string 8 'vw'  */
2823     3,   1,    /* string 9 'bmw' */
2824     8,   4,    /* string 10 'Property' */
2825     5,   1,    /* string 11 'Value' */
2826     4,   1,    /* string 12 'prop' */
2827     3,   1,    /* string 13 'val' */
2828 };
2829 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2830 static const WCHAR data6[] = { /* MOO */
2831     0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2832     0x0000, 0x8003,         /* delete row */
2833 };
2834
2835 static const WCHAR data7[] = { /* BINARY */
2836     0x0201, 0x8001, 0x0001,
2837 };
2838
2839 static const char data8[] =  /* stream data for the BINARY table */
2840     "naengmyon";
2841
2842 static const WCHAR data9[] = { /* Property */
2843     0x0201, 0x000c, 0x000d,
2844 };
2845
2846 static const struct {
2847     LPCWSTR name;
2848     const void *data;
2849     DWORD size;
2850 } table_transform_data[] =
2851 {
2852     { name1, data1, sizeof data1 },
2853     { name2, data2, sizeof data2 },
2854     { name3, data3, sizeof data3 },
2855     { name4, data4, sizeof data4 - 1 },
2856     { name5, data5, sizeof data5 },
2857     { name6, data6, sizeof data6 },
2858     { name7, data7, sizeof data7 },
2859     { name8, data8, sizeof data8 - 1 },
2860     { name9, data9, sizeof data9 },
2861 };
2862
2863 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2864
2865 static void generate_transform_manual(void)
2866 {
2867     IStorage *stg = NULL;
2868     IStream *stm;
2869     WCHAR name[0x20];
2870     HRESULT r;
2871     DWORD i, count;
2872     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2873
2874     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2875
2876     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2877
2878     r = StgCreateDocfile(name, mode, 0, &stg);
2879     ok(r == S_OK, "failed to create storage\n");
2880     if (!stg)
2881         return;
2882
2883     r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2884     ok(r == S_OK, "failed to set storage type\n");
2885
2886     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2887     {
2888         r = IStorage_CreateStream( stg, table_transform_data[i].name,
2889                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2890         if (FAILED(r))
2891         {
2892             ok(0, "failed to create stream %08x\n", r);
2893             continue;
2894         }
2895
2896         r = IStream_Write( stm, table_transform_data[i].data,
2897                           table_transform_data[i].size, &count );
2898         if (FAILED(r) || count != table_transform_data[i].size)
2899             ok(0, "failed to write stream\n");
2900         IStream_Release(stm);
2901     }
2902
2903     IStorage_Release(stg);
2904 }
2905
2906 static UINT set_summary_info(MSIHANDLE hdb)
2907 {
2908     UINT res;
2909     MSIHANDLE suminfo;
2910
2911     /* build summary info */
2912     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
2913     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2914
2915     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
2916                         "Installation Database");
2917     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2918
2919     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
2920                         "Installation Database");
2921     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2922
2923     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
2924                         "Wine Hackers");
2925     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2926
2927     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
2928                     ";1033,2057");
2929     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2930
2931     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
2932                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
2933     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2934
2935     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
2936     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2937
2938     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
2939     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2940
2941     res = MsiSummaryInfoPersist(suminfo);
2942     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
2943
2944     res = MsiCloseHandle( suminfo);
2945     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
2946
2947     return res;
2948 }
2949
2950 static MSIHANDLE create_package_db(LPCSTR filename)
2951 {
2952     MSIHANDLE hdb = 0;
2953     UINT res;
2954
2955     DeleteFile(msifile);
2956
2957     /* create an empty database */
2958     res = MsiOpenDatabase(filename, MSIDBOPEN_CREATE, &hdb );
2959     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
2960     if( res != ERROR_SUCCESS )
2961         return hdb;
2962
2963     res = MsiDatabaseCommit( hdb );
2964     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
2965
2966     res = set_summary_info(hdb);
2967     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2968
2969     res = create_directory_table(hdb);
2970     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
2971
2972     return hdb;
2973 }
2974
2975 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
2976 {
2977     UINT res;
2978     CHAR szPackage[12];
2979     MSIHANDLE hPackage;
2980
2981     sprintf(szPackage, "#%u", hdb);
2982     res = MsiOpenPackage(szPackage, &hPackage);
2983     if (res != ERROR_SUCCESS)
2984         return res;
2985
2986     res = MsiCloseHandle(hdb);
2987     if (res != ERROR_SUCCESS)
2988     {
2989         MsiCloseHandle(hPackage);
2990         return res;
2991     }
2992
2993     *handle = hPackage;
2994     return ERROR_SUCCESS;
2995 }
2996
2997 static void test_try_transform(void)
2998 {
2999     MSIHANDLE hdb, hview, hrec, hpkg = 0;
3000     LPCSTR query;
3001     UINT r;
3002     DWORD sz;
3003     char buffer[MAX_PATH];
3004
3005     DeleteFile(msifile);
3006     DeleteFile(mstfile);
3007
3008     /* create the database */
3009     hdb = create_package_db(msifile);
3010     ok(hdb, "Failed to create package db\n");
3011
3012     query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
3013     r = run_query(hdb, 0, query);
3014     ok(r == ERROR_SUCCESS, "failed to add table\n");
3015
3016     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
3017     r = run_query(hdb, 0, query);
3018     ok(r == ERROR_SUCCESS, "failed to add row\n");
3019
3020     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
3021     r = run_query(hdb, 0, query);
3022     ok(r == ERROR_SUCCESS, "failed to add row\n");
3023
3024     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
3025     r = run_query(hdb, 0, query);
3026     ok(r == ERROR_SUCCESS, "failed to add row\n");
3027
3028     query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
3029     r = run_query(hdb, 0, query);
3030     ok(r == ERROR_SUCCESS, "failed to add table\n");
3031
3032     hrec = MsiCreateRecord(2);
3033     r = MsiRecordSetInteger(hrec, 1, 2);
3034     ok(r == ERROR_SUCCESS, "failed to set integer\n");
3035
3036     write_file("testdata.bin", "lamyon", 6);
3037     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
3038     ok(r == ERROR_SUCCESS, "failed to set stream\n");
3039
3040     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3041     r = run_query(hdb, hrec, query);
3042     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3043
3044     MsiCloseHandle(hrec);
3045
3046     r = MsiDatabaseCommit( hdb );
3047     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3048
3049     MsiCloseHandle( hdb );
3050     DeleteFileA("testdata.bin");
3051
3052     /*
3053      * Both these generate an equivalent transform,
3054      *  but the first doesn't work in Wine yet
3055      *  because MsiDatabaseGenerateTransform is unimplemented.
3056      */
3057     if (0)
3058         generate_transform();
3059     else
3060         generate_transform_manual();
3061
3062     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb );
3063     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3064
3065     r = MsiDatabaseApplyTransform( hdb, mstfile, 0 );
3066     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3067
3068     MsiDatabaseCommit( hdb );
3069
3070     /* check new values */
3071     hrec = 0;
3072     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3073     r = do_query(hdb, query, &hrec);
3074     ok(r == ERROR_SUCCESS, "select query failed\n");
3075     MsiCloseHandle(hrec);
3076
3077     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3078     hrec = 0;
3079     r = do_query(hdb, query, &hrec);
3080     ok(r == ERROR_SUCCESS, "select query failed\n");
3081     MsiCloseHandle(hrec);
3082
3083     /* check updated values */
3084     hrec = 0;
3085     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3086     r = do_query(hdb, query, &hrec);
3087     ok(r == ERROR_SUCCESS, "select query failed\n");
3088     MsiCloseHandle(hrec);
3089
3090     /* check unchanged value */
3091     hrec = 0;
3092     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3093     r = do_query(hdb, query, &hrec);
3094     ok(r == ERROR_SUCCESS, "select query failed\n");
3095     MsiCloseHandle(hrec);
3096
3097     /* check deleted value */
3098     hrec = 0;
3099     query = "select * from `MOO` where `NOO` = 3";
3100     r = do_query(hdb, query, &hrec);
3101     ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3102     if (hrec) MsiCloseHandle(hrec);
3103
3104     /* check added stream */
3105     hrec = 0;
3106     query = "select `BLOB` from `BINARY` where `ID` = 1";
3107     r = do_query(hdb, query, &hrec);
3108     ok(r == ERROR_SUCCESS, "select query failed\n");
3109
3110     /* check the contents of the stream */
3111     sz = sizeof buffer;
3112     r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3113     ok(r == ERROR_SUCCESS, "read stream failed\n");
3114     ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3115     ok(sz == 9, "stream data was wrong size\n");
3116     if (hrec) MsiCloseHandle(hrec);
3117
3118     /* check the validity of the table with a deleted row */
3119     hrec = 0;
3120     query = "select * from `MOO`";
3121     r = MsiDatabaseOpenView(hdb, query, &hview);
3122     ok(r == ERROR_SUCCESS, "open view failed\n");
3123
3124     r = MsiViewExecute(hview, 0);
3125     ok(r == ERROR_SUCCESS, "view execute failed\n");
3126
3127     r = MsiViewFetch(hview, &hrec);
3128     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3129
3130     r = MsiRecordGetInteger(hrec, 1);
3131     ok(r == 1, "Expected 1, got %d\n", r);
3132
3133     sz = sizeof buffer;
3134     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3135     ok(r == ERROR_SUCCESS, "record get string failed\n");
3136     ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3137
3138     r = MsiRecordGetInteger(hrec, 3);
3139     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3140
3141     r = MsiRecordGetInteger(hrec, 4);
3142     ok(r == 5, "Expected 5, got %d\n", r);
3143
3144     MsiCloseHandle(hrec);
3145
3146     r = MsiViewFetch(hview, &hrec);
3147     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3148
3149     r = MsiRecordGetInteger(hrec, 1);
3150     ok(r == 2, "Expected 2, got %d\n", r);
3151
3152     sz = sizeof buffer;
3153     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3154     ok(r == ERROR_SUCCESS, "record get string failed\n");
3155     ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3156
3157     r = MsiRecordGetInteger(hrec, 3);
3158     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3159
3160     r = MsiRecordGetInteger(hrec, 4);
3161     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3162
3163     MsiCloseHandle(hrec);
3164
3165     r = MsiViewFetch(hview, &hrec);
3166     ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3167
3168     MsiCloseHandle(hrec);
3169     MsiViewClose(hview);
3170     MsiCloseHandle(hview);
3171
3172     /* check that the property was added */
3173     r = package_from_db(hdb, &hpkg);
3174     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3175     {
3176         skip("Not enough rights to perform tests\n");
3177         goto error;
3178     }
3179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3180
3181     sz = MAX_PATH;
3182     r = MsiGetProperty(hpkg, "prop", buffer, &sz);
3183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3184     ok(!lstrcmp(buffer, "val"), "Expected val, got %s\n", buffer);
3185
3186     MsiCloseHandle(hpkg);
3187
3188 error:
3189     MsiCloseHandle(hdb);
3190     DeleteFile(msifile);
3191     DeleteFile(mstfile);
3192 }
3193
3194 struct join_res
3195 {
3196     const CHAR one[MAX_PATH];
3197     const CHAR two[MAX_PATH];
3198 };
3199
3200 struct join_res_4col
3201 {
3202     const CHAR one[MAX_PATH];
3203     const CHAR two[MAX_PATH];
3204     const CHAR three[MAX_PATH];
3205     const CHAR four[MAX_PATH];
3206 };
3207
3208 struct join_res_uint
3209 {
3210     UINT one;
3211     UINT two;
3212     UINT three;
3213     UINT four;
3214     UINT five;
3215     UINT six;
3216 };
3217
3218 static const struct join_res join_res_first[] =
3219 {
3220     { "alveolar", "procerus" },
3221     { "septum", "procerus" },
3222     { "septum", "nasalis" },
3223     { "ramus", "nasalis" },
3224     { "malar", "mentalis" },
3225 };
3226
3227 static const struct join_res join_res_second[] =
3228 {
3229     { "nasal", "septum" },
3230     { "mandible", "ramus" },
3231 };
3232
3233 static const struct join_res join_res_third[] =
3234 {
3235     { "msvcp.dll", "abcdefgh" },
3236     { "msvcr.dll", "ijklmnop" },
3237 };
3238
3239 static const struct join_res join_res_fourth[] =
3240 {
3241     { "msvcp.dll.01234", "single.dll.31415" },
3242 };
3243
3244 static const struct join_res join_res_fifth[] =
3245 {
3246     { "malar", "procerus" },
3247 };
3248
3249 static const struct join_res join_res_sixth[] =
3250 {
3251     { "malar", "procerus" },
3252     { "malar", "procerus" },
3253     { "malar", "nasalis" },
3254     { "malar", "nasalis" },
3255     { "malar", "nasalis" },
3256     { "malar", "mentalis" },
3257 };
3258
3259 static const struct join_res join_res_seventh[] =
3260 {
3261     { "malar", "nasalis" },
3262     { "malar", "nasalis" },
3263     { "malar", "nasalis" },
3264 };
3265
3266 static const struct join_res_4col join_res_eighth[] =
3267 {
3268     { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3269     { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3270     { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3271     { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3272     { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3273     { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3274 };
3275
3276 static const struct join_res_uint join_res_ninth[] =
3277 {
3278     { 1, 2, 3, 4, 7, 8 },
3279     { 1, 2, 5, 6, 7, 8 },
3280     { 1, 2, 3, 4, 9, 10 },
3281     { 1, 2, 5, 6, 9, 10 },
3282     { 1, 2, 3, 4, 11, 12 },
3283     { 1, 2, 5, 6, 11, 12 },
3284 };
3285
3286 static void test_join(void)
3287 {
3288     MSIHANDLE hdb, hview, hrec;
3289     LPCSTR query;
3290     CHAR buf[MAX_PATH];
3291     UINT r, count;
3292     DWORD size, i;
3293     BOOL data_correct;
3294
3295     hdb = create_db();
3296     ok( hdb, "failed to create db\n");
3297
3298     r = create_component_table( hdb );
3299     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3300
3301     r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3302     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3303
3304     r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3305     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3306
3307     r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3308     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3309
3310     r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3311     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3312
3313     r = create_feature_components_table( hdb );
3314     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3315
3316     r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3317     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3318
3319     r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3320     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3321
3322     r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3323     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3324
3325     r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3326     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3327
3328     r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3329     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3330
3331     r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3332     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3333
3334     r = create_std_dlls_table( hdb );
3335     ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3336
3337     r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3338     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3339
3340     r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3341     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3342
3343     r = create_binary_table( hdb );
3344     ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3345
3346     r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3347     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3348
3349     r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3350     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3351
3352     r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3353     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3354
3355     query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3356     r = run_query( hdb, 0, query);
3357     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3358
3359     query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3360     r = run_query( hdb, 0, query);
3361     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3362
3363     query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3364     r = run_query( hdb, 0, query);
3365     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3366
3367     query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3368     r = run_query( hdb, 0, query);
3369     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3370
3371     query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3372     r = run_query( hdb, 0, query);
3373     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3374
3375     query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3376     r = run_query( hdb, 0, query);
3377     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3378
3379     query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3380     r = run_query( hdb, 0, query);
3381     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3382
3383     query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3384     r = run_query( hdb, 0, query);
3385     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3386
3387     query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3388     r = run_query( hdb, 0, query);
3389     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3390
3391     query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3392     r = run_query( hdb, 0, query);
3393     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3394
3395     query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3396     r = run_query( hdb, 0, query);
3397     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3398
3399     query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3400     r = run_query( hdb, 0, query);
3401     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3402
3403     query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3404     r = run_query( hdb, 0, query);
3405     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3406
3407     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3408             "FROM `Component`, `FeatureComponents` "
3409             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3410             "ORDER BY `Feature_`";
3411     r = MsiDatabaseOpenView(hdb, query, &hview);
3412     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3413
3414     r = MsiViewExecute(hview, 0);
3415     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3416
3417     i = 0;
3418     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3419     {
3420         count = MsiRecordGetFieldCount( hrec );
3421         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3422
3423         size = MAX_PATH;
3424         r = MsiRecordGetString( hrec, 1, buf, &size );
3425         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3426         ok( !lstrcmp( buf, join_res_first[i].one ),
3427             "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3428
3429         size = MAX_PATH;
3430         r = MsiRecordGetString( hrec, 2, buf, &size );
3431         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3432         ok( !lstrcmp( buf, join_res_first[i].two ),
3433             "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3434
3435         i++;
3436         MsiCloseHandle(hrec);
3437     }
3438
3439     ok( i == 5, "Expected 5 rows, got %d\n", i );
3440     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3441
3442     MsiViewClose(hview);
3443     MsiCloseHandle(hview);
3444
3445     /* try a join without a WHERE condition */
3446     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3447             "FROM `Component`, `FeatureComponents` ";
3448     r = MsiDatabaseOpenView(hdb, query, &hview);
3449     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3450
3451     r = MsiViewExecute(hview, 0);
3452     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3453
3454     i = 0;
3455     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3456     {
3457         i++;
3458         MsiCloseHandle(hrec);
3459     }
3460     ok( i == 24, "Expected 24 rows, got %d\n", i );
3461
3462     MsiViewClose(hview);
3463     MsiCloseHandle(hview);
3464
3465     query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3466             "WHERE FeatureComponents.Component_=Component.Component "
3467             "AND (Feature_='nasalis') ORDER BY Feature_";
3468     r = MsiDatabaseOpenView(hdb, query, &hview);
3469     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3470
3471     r = MsiViewExecute(hview, 0);
3472     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3473
3474     i = 0;
3475     data_correct = TRUE;
3476     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3477     {
3478         count = MsiRecordGetFieldCount( hrec );
3479         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3480
3481         size = MAX_PATH;
3482         r = MsiRecordGetString( hrec, 1, buf, &size );
3483         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3484         if( lstrcmp( buf, join_res_second[i].one ))
3485             data_correct = FALSE;
3486
3487         size = MAX_PATH;
3488         r = MsiRecordGetString( hrec, 2, buf, &size );
3489         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3490         if( lstrcmp( buf, join_res_second[i].two ))
3491             data_correct = FALSE;
3492
3493         i++;
3494         MsiCloseHandle(hrec);
3495     }
3496
3497     ok( data_correct, "data returned in the wrong order\n");
3498
3499     ok( i == 2, "Expected 2 rows, got %d\n", i );
3500     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3501
3502     MsiViewClose(hview);
3503     MsiCloseHandle(hview);
3504
3505     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3506             "FROM `StdDlls`, `Binary` "
3507             "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3508             "ORDER BY `File`";
3509     r = MsiDatabaseOpenView(hdb, query, &hview);
3510     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3511
3512     r = MsiViewExecute(hview, 0);
3513     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3514
3515     i = 0;
3516     data_correct = TRUE;
3517     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3518     {
3519         count = MsiRecordGetFieldCount( hrec );
3520         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3521
3522         size = MAX_PATH;
3523         r = MsiRecordGetString( hrec, 1, buf, &size );
3524         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3525         if( lstrcmp( buf, join_res_third[i].one ) )
3526             data_correct = FALSE;
3527
3528         size = MAX_PATH;
3529         r = MsiRecordGetString( hrec, 2, buf, &size );
3530         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3531         if( lstrcmp( buf, join_res_third[i].two ) )
3532             data_correct = FALSE;
3533
3534         i++;
3535         MsiCloseHandle(hrec);
3536     }
3537     ok( data_correct, "data returned in the wrong order\n");
3538
3539     ok( i == 2, "Expected 2 rows, got %d\n", i );
3540
3541     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3542
3543     MsiViewClose(hview);
3544     MsiCloseHandle(hview);
3545
3546     query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3547             "FROM `StdDlls`, `Binary` "
3548             "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3549             "ORDER BY `Name`";
3550     r = MsiDatabaseOpenView(hdb, query, &hview);
3551     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3552
3553     r = MsiViewExecute(hview, 0);
3554     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3555
3556     i = 0;
3557     data_correct = TRUE;
3558     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3559     {
3560         count = MsiRecordGetFieldCount( hrec );
3561         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3562
3563         size = MAX_PATH;
3564         r = MsiRecordGetString( hrec, 1, buf, &size );
3565         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3566         if( lstrcmp( buf, join_res_fourth[i].one ))
3567             data_correct = FALSE;
3568
3569         size = MAX_PATH;
3570         r = MsiRecordGetString( hrec, 2, buf, &size );
3571         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3572         if( lstrcmp( buf, join_res_fourth[i].two ))
3573             data_correct = FALSE;
3574
3575         i++;
3576         MsiCloseHandle(hrec);
3577     }
3578     ok( data_correct, "data returned in the wrong order\n");
3579
3580     ok( i == 1, "Expected 1 rows, got %d\n", i );
3581     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3582
3583     MsiViewClose(hview);
3584     MsiCloseHandle(hview);
3585
3586     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3587             "FROM `Component`, `FeatureComponents` "
3588             "WHERE `Component`.`Component` = 'zygomatic' "
3589             "AND `FeatureComponents`.`Component_` = 'maxilla' "
3590             "ORDER BY `Feature_`";
3591     r = MsiDatabaseOpenView(hdb, query, &hview);
3592     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3593
3594     r = MsiViewExecute(hview, 0);
3595     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3596
3597     i = 0;
3598     data_correct = TRUE;
3599     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3600     {
3601         count = MsiRecordGetFieldCount( hrec );
3602         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3603
3604         size = MAX_PATH;
3605         r = MsiRecordGetString( hrec, 1, buf, &size );
3606         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3607         if( lstrcmp( buf, join_res_fifth[i].one ))
3608             data_correct = FALSE;
3609
3610         size = MAX_PATH;
3611         r = MsiRecordGetString( hrec, 2, buf, &size );
3612         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3613         if( lstrcmp( buf, join_res_fifth[i].two ))
3614             data_correct = FALSE;
3615
3616         i++;
3617         MsiCloseHandle(hrec);
3618     }
3619     ok( data_correct, "data returned in the wrong order\n");
3620
3621     ok( i == 1, "Expected 1 rows, got %d\n", i );
3622     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3623
3624     MsiViewClose(hview);
3625     MsiCloseHandle(hview);
3626
3627     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3628             "FROM `Component`, `FeatureComponents` "
3629             "WHERE `Component` = 'zygomatic' "
3630             "ORDER BY `Feature_`";
3631     r = MsiDatabaseOpenView(hdb, query, &hview);
3632     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3633
3634     r = MsiViewExecute(hview, 0);
3635     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3636
3637     i = 0;
3638     data_correct = TRUE;
3639     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3640     {
3641         count = MsiRecordGetFieldCount( hrec );
3642         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3643
3644         size = MAX_PATH;
3645         r = MsiRecordGetString( hrec, 1, buf, &size );
3646         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3647         if( lstrcmp( buf, join_res_sixth[i].one ))
3648             data_correct = FALSE;
3649
3650         size = MAX_PATH;
3651         r = MsiRecordGetString( hrec, 2, buf, &size );
3652         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3653         if( lstrcmp( buf, join_res_sixth[i].two ))
3654             data_correct = FALSE;
3655
3656         i++;
3657         MsiCloseHandle(hrec);
3658     }
3659     ok( data_correct, "data returned in the wrong order\n");
3660
3661     ok( i == 6, "Expected 6 rows, got %d\n", i );
3662     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3663
3664     MsiViewClose(hview);
3665     MsiCloseHandle(hview);
3666
3667     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3668             "FROM `Component`, `FeatureComponents` "
3669             "WHERE `Component` = 'zygomatic' "
3670             "AND `Feature_` = 'nasalis' "
3671             "ORDER BY `Feature_`";
3672     r = MsiDatabaseOpenView(hdb, query, &hview);
3673     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3674
3675     r = MsiViewExecute(hview, 0);
3676     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3677
3678     i = 0;
3679     data_correct = TRUE;
3680     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3681     {
3682         count = MsiRecordGetFieldCount( hrec );
3683         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3684
3685         size = MAX_PATH;
3686         r = MsiRecordGetString( hrec, 1, buf, &size );
3687         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3688         if( lstrcmp( buf, join_res_seventh[i].one ))
3689             data_correct = FALSE;
3690
3691         size = MAX_PATH;
3692         r = MsiRecordGetString( hrec, 2, buf, &size );
3693         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3694         if( lstrcmp( buf, join_res_seventh[i].two ))
3695             data_correct = FALSE;
3696
3697         i++;
3698         MsiCloseHandle(hrec);
3699     }
3700
3701     ok( data_correct, "data returned in the wrong order\n");
3702     ok( i == 3, "Expected 3 rows, got %d\n", i );
3703     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3704
3705     MsiViewClose(hview);
3706     MsiCloseHandle(hview);
3707
3708     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3709             "FROM `StdDlls`, `Binary` ";
3710     r = MsiDatabaseOpenView(hdb, query, &hview);
3711     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3712
3713     r = MsiViewExecute(hview, 0);
3714     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3715
3716     i = 0;
3717     data_correct = TRUE;
3718     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3719     {
3720         count = MsiRecordGetFieldCount( hrec );
3721         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3722
3723         size = MAX_PATH;
3724         r = MsiRecordGetString( hrec, 1, buf, &size );
3725         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3726         if( lstrcmp( buf, join_res_eighth[i].one ))
3727             data_correct = FALSE;
3728
3729         size = MAX_PATH;
3730         r = MsiRecordGetString( hrec, 2, buf, &size );
3731         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3732         if( lstrcmp( buf, join_res_eighth[i].four ))
3733             data_correct = FALSE;
3734
3735         i++;
3736         MsiCloseHandle(hrec);
3737     }
3738
3739     ok( data_correct, "data returned in the wrong order\n");
3740     ok( i == 6, "Expected 6 rows, got %d\n", i );
3741     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3742
3743     MsiViewClose(hview);
3744     MsiCloseHandle(hview);
3745
3746     query = "SELECT * FROM `StdDlls`, `Binary` ";
3747     r = MsiDatabaseOpenView(hdb, query, &hview);
3748     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3749
3750     r = MsiViewExecute(hview, 0);
3751     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3752
3753     i = 0;
3754     data_correct = TRUE;
3755     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3756     {
3757         count = MsiRecordGetFieldCount( hrec );
3758         ok( count == 4, "Expected 4 record fields, got %d\n", count );
3759
3760         size = MAX_PATH;
3761         r = MsiRecordGetString( hrec, 1, buf, &size );
3762         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3763         if( lstrcmp( buf, join_res_eighth[i].one ))
3764             data_correct = FALSE;
3765
3766         size = MAX_PATH;
3767         r = MsiRecordGetString( hrec, 2, buf, &size );
3768         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3769         if( lstrcmp( buf, join_res_eighth[i].two ))
3770             data_correct = FALSE;
3771
3772         size = MAX_PATH;
3773         r = MsiRecordGetString( hrec, 3, buf, &size );
3774         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3775         if( lstrcmp( buf, join_res_eighth[i].three ))
3776             data_correct = FALSE;
3777
3778         size = MAX_PATH;
3779         r = MsiRecordGetString( hrec, 4, buf, &size );
3780         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3781         if( lstrcmp( buf, join_res_eighth[i].four ))
3782             data_correct = FALSE;
3783
3784         i++;
3785         MsiCloseHandle(hrec);
3786     }
3787     ok( data_correct, "data returned in the wrong order\n");
3788
3789     ok( i == 6, "Expected 6 rows, got %d\n", i );
3790     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3791
3792     MsiViewClose(hview);
3793     MsiCloseHandle(hview);
3794
3795     query = "SELECT * FROM `One`, `Two`, `Three` ";
3796     r = MsiDatabaseOpenView(hdb, query, &hview);
3797     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3798
3799     r = MsiViewExecute(hview, 0);
3800     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3801
3802     i = 0;
3803     data_correct = TRUE;
3804     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3805     {
3806         count = MsiRecordGetFieldCount( hrec );
3807         ok( count == 6, "Expected 6 record fields, got %d\n", count );
3808
3809         r = MsiRecordGetInteger( hrec, 1 );
3810         if( r != join_res_ninth[i].one )
3811             data_correct = FALSE;
3812
3813         r = MsiRecordGetInteger( hrec, 2 );
3814         if( r != join_res_ninth[i].two )
3815             data_correct = FALSE;
3816
3817         r = MsiRecordGetInteger( hrec, 3 );
3818         if( r != join_res_ninth[i].three )
3819             data_correct = FALSE;
3820
3821         r = MsiRecordGetInteger( hrec, 4 );
3822         if( r != join_res_ninth[i].four )
3823             data_correct = FALSE;
3824
3825         r = MsiRecordGetInteger( hrec, 5 );
3826         if( r != join_res_ninth[i].five )
3827             data_correct = FALSE;
3828
3829         r = MsiRecordGetInteger( hrec, 6);
3830         if( r != join_res_ninth[i].six )
3831             data_correct = FALSE;
3832
3833         i++;
3834         MsiCloseHandle(hrec);
3835     }
3836     ok( data_correct, "data returned in the wrong order\n");
3837
3838     ok( i == 6, "Expected 6 rows, got %d\n", i );
3839     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3840
3841     MsiViewClose(hview);
3842     MsiCloseHandle(hview);
3843
3844     query = "SELECT * FROM `Four`, `Five`";
3845     r = MsiDatabaseOpenView(hdb, query, &hview);
3846     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3847
3848     r = MsiViewExecute(hview, 0);
3849     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3850
3851     r = MsiViewFetch(hview, &hrec);
3852     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3853
3854     MsiViewClose(hview);
3855     MsiCloseHandle(hview);
3856
3857     query = "SELECT * FROM `Nonexistent`, `One`";
3858     r = MsiDatabaseOpenView(hdb, query, &hview);
3859     ok( r == ERROR_BAD_QUERY_SYNTAX,
3860         "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3861
3862     /* try updating a row in a join table */
3863     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3864             "FROM `Component`, `FeatureComponents` "
3865             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3866             "ORDER BY `Feature_`";
3867     r = MsiDatabaseOpenView(hdb, query, &hview);
3868     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3869
3870     r = MsiViewExecute(hview, 0);
3871     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3872
3873     r = MsiViewFetch(hview, &hrec);
3874     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3875
3876     r = MsiRecordSetString( hrec, 1, "epicranius" );
3877     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3878
3879     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3880     ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3881
3882     /* try another valid operation for joins */
3883     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3884     todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3885
3886     /* try an invalid operation for joins */
3887     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3888     ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3889
3890     r = MsiRecordSetString( hrec, 2, "epicranius" );
3891     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3892
3893     /* primary key cannot be updated */
3894     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3895     todo_wine ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3896
3897     MsiCloseHandle(hrec);
3898     MsiViewClose(hview);
3899     MsiCloseHandle(hview);
3900
3901     r = MsiDatabaseOpenView(hdb, query, &hview);
3902     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3903
3904     r = MsiViewExecute(hview, 0);
3905     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3906
3907     r = MsiViewFetch(hview, &hrec);
3908     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3909
3910     size = MAX_PATH;
3911     r = MsiRecordGetString( hrec, 1, buf, &size );
3912     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3913     ok( !lstrcmp( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
3914
3915     MsiCloseHandle(hrec);
3916     MsiViewClose(hview);
3917     MsiCloseHandle(hview);
3918
3919     MsiCloseHandle(hdb);
3920     DeleteFile(msifile);
3921 }
3922
3923 static void test_temporary_table(void)
3924 {
3925     MSICONDITION cond;
3926     MSIHANDLE hdb = 0, view = 0, rec;
3927     const char *query;
3928     UINT r;
3929     char buf[0x10];
3930     DWORD sz;
3931
3932     cond = MsiDatabaseIsTablePersistent(0, NULL);
3933     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3934
3935     hdb = create_db();
3936     ok( hdb, "failed to create db\n");
3937
3938     cond = MsiDatabaseIsTablePersistent(hdb, NULL);
3939     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3940
3941     cond = MsiDatabaseIsTablePersistent(hdb, "_Tables");
3942     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3943
3944     cond = MsiDatabaseIsTablePersistent(hdb, "_Columns");
3945     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3946
3947     cond = MsiDatabaseIsTablePersistent(hdb, "_Storages");
3948     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3949
3950     cond = MsiDatabaseIsTablePersistent(hdb, "_Streams");
3951     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3952
3953     query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
3954     r = run_query(hdb, 0, query);
3955     ok(r == ERROR_SUCCESS, "failed to add table\n");
3956
3957     cond = MsiDatabaseIsTablePersistent(hdb, "P");
3958     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3959
3960     query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
3961     r = run_query(hdb, 0, query);
3962     ok(r == ERROR_SUCCESS, "failed to add table\n");
3963
3964     cond = MsiDatabaseIsTablePersistent(hdb, "P2");
3965     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3966
3967     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
3968     r = run_query(hdb, 0, query);
3969     ok(r == ERROR_SUCCESS, "failed to add table\n");
3970
3971     cond = MsiDatabaseIsTablePersistent(hdb, "T");
3972     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
3973
3974     query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3975     r = run_query(hdb, 0, query);
3976     ok(r == ERROR_SUCCESS, "failed to add table\n");
3977
3978     query = "SELECT * FROM `T2`";
3979     r = MsiDatabaseOpenView(hdb, query, &view);
3980     ok(r == ERROR_BAD_QUERY_SYNTAX,
3981        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3982
3983     cond = MsiDatabaseIsTablePersistent(hdb, "T2");
3984     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3985
3986     query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
3987     r = run_query(hdb, 0, query);
3988     ok(r == ERROR_SUCCESS, "failed to add table\n");
3989
3990     cond = MsiDatabaseIsTablePersistent(hdb, "T3");
3991     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3992
3993     query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3994     r = run_query(hdb, 0, query);
3995     ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
3996
3997     cond = MsiDatabaseIsTablePersistent(hdb, "T4");
3998     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3999
4000     query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
4001     r = run_query(hdb, 0, query);
4002     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
4003
4004     query = "select * from `T`";
4005     r = MsiDatabaseOpenView(hdb, query, &view);
4006     ok(r == ERROR_SUCCESS, "failed to query table\n");
4007     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4008     ok(r == ERROR_SUCCESS, "failed to get column info\n");
4009
4010     sz = sizeof buf;
4011     r = MsiRecordGetString(rec, 1, buf, &sz);
4012     ok(r == ERROR_SUCCESS, "failed to get string\n");
4013     ok( 0 == strcmp("G255", buf), "wrong column type\n");
4014
4015     sz = sizeof buf;
4016     r = MsiRecordGetString(rec, 2, buf, &sz);
4017     ok(r == ERROR_SUCCESS, "failed to get string\n");
4018     ok( 0 == strcmp("j2", buf), "wrong column type\n");
4019
4020     MsiCloseHandle( rec );
4021     MsiViewClose( view );
4022     MsiCloseHandle( view );
4023
4024     /* query the table data */
4025     rec = 0;
4026     r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
4027     ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
4028     MsiCloseHandle( rec );
4029
4030     /* query the column data */
4031     rec = 0;
4032     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
4033     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4034     if (rec) MsiCloseHandle( rec );
4035
4036     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
4037     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4038     if (rec) MsiCloseHandle( rec );
4039
4040     MsiCloseHandle( hdb );
4041
4042     DeleteFile(msifile);
4043 }
4044
4045 static void test_alter(void)
4046 {
4047     MSICONDITION cond;
4048     MSIHANDLE hdb = 0;
4049     const char *query;
4050     UINT r;
4051
4052     hdb = create_db();
4053     ok( hdb, "failed to create db\n");
4054
4055     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4056     r = run_query(hdb, 0, query);
4057     ok(r == ERROR_SUCCESS, "failed to add table\n");
4058
4059     cond = MsiDatabaseIsTablePersistent(hdb, "T");
4060     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4061
4062     query = "ALTER TABLE `T` HOLD";
4063     r = run_query(hdb, 0, query);
4064     ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4065
4066     query = "ALTER TABLE `T` FREE";
4067     r = run_query(hdb, 0, query);
4068     ok(r == ERROR_SUCCESS, "failed to free table\n");
4069
4070     query = "ALTER TABLE `T` FREE";
4071     r = run_query(hdb, 0, query);
4072     ok(r == ERROR_SUCCESS, "failed to free table\n");
4073
4074     query = "ALTER TABLE `T` FREE";
4075     r = run_query(hdb, 0, query);
4076     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4077
4078     query = "ALTER TABLE `T` HOLD";
4079     r = run_query(hdb, 0, query);
4080     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4081
4082     /* table T is removed */
4083     query = "SELECT * FROM `T`";
4084     r = run_query(hdb, 0, query);
4085     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4086
4087     /* create the table again */
4088     query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4089     r = run_query(hdb, 0, query);
4090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4091
4092     /* up the ref count */
4093     query = "ALTER TABLE `U` HOLD";
4094     r = run_query(hdb, 0, query);
4095     ok(r == ERROR_SUCCESS, "failed to free table\n");
4096
4097     /* add column, no data type */
4098     query = "ALTER TABLE `U` ADD `C`";
4099     r = run_query(hdb, 0, query);
4100     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4101
4102     query = "ALTER TABLE `U` ADD `C` INTEGER";
4103     r = run_query(hdb, 0, query);
4104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4105
4106     /* add column C again */
4107     query = "ALTER TABLE `U` ADD `C` INTEGER";
4108     r = run_query(hdb, 0, query);
4109     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4110
4111     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4112     r = run_query(hdb, 0, query);
4113     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4114
4115     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4116     r = run_query(hdb, 0, query);
4117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4118
4119     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4120     r = run_query(hdb, 0, query);
4121     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4122
4123     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4124     r = run_query(hdb, 0, query);
4125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4126
4127     query = "SELECT * FROM `U` WHERE `D` = 8";
4128     r = run_query(hdb, 0, query);
4129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4130
4131     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4132     r = run_query(hdb, 0, query);
4133     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4134
4135     query = "ALTER COLUMN `D` FREE";
4136     r = run_query(hdb, 0, query);
4137     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4138
4139     /* drop the ref count */
4140     query = "ALTER TABLE `U` FREE";
4141     r = run_query(hdb, 0, query);
4142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4143
4144     /* table is not empty */
4145     query = "SELECT * FROM `U`";
4146     r = run_query(hdb, 0, query);
4147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4148
4149     /* column D is removed */
4150     query = "SELECT * FROM `U` WHERE `D` = 8";
4151     r = run_query(hdb, 0, query);
4152     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4153
4154     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4155     r = run_query(hdb, 0, query);
4156     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4157
4158     /* add the column again */
4159     query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4160     r = run_query(hdb, 0, query);
4161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4162
4163     /* up the ref count */
4164     query = "ALTER TABLE `U` HOLD";
4165     r = run_query(hdb, 0, query);
4166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4167
4168     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4169     r = run_query(hdb, 0, query);
4170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4171
4172     query = "SELECT * FROM `U` WHERE `E` = 16";
4173     r = run_query(hdb, 0, query);
4174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4175
4176     /* drop the ref count */
4177     query = "ALTER TABLE `U` FREE";
4178     r = run_query(hdb, 0, query);
4179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4180
4181     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4182     r = run_query(hdb, 0, query);
4183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4184
4185     query = "SELECT * FROM `U` WHERE `E` = 20";
4186     r = run_query(hdb, 0, query);
4187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4188
4189     /* drop the ref count */
4190     query = "ALTER TABLE `U` FREE";
4191     r = run_query(hdb, 0, query);
4192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4193
4194     /* table still exists */
4195     query = "SELECT * FROM `U`";
4196     r = run_query(hdb, 0, query);
4197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4198
4199     /* col E is removed */
4200     query = "SELECT * FROM `U` WHERE `E` = 20";
4201     r = run_query(hdb, 0, query);
4202     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4203
4204     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4205     r = run_query(hdb, 0, query);
4206     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4207
4208     /* drop the ref count once more */
4209     query = "ALTER TABLE `U` FREE";
4210     r = run_query(hdb, 0, query);
4211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4212
4213     /* table still exists */
4214     query = "SELECT * FROM `U`";
4215     r = run_query(hdb, 0, query);
4216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4217
4218     MsiCloseHandle( hdb );
4219     DeleteFile(msifile);
4220 }
4221
4222 static void test_integers(void)
4223 {
4224     MSIHANDLE hdb = 0, view = 0, rec = 0;
4225     DWORD count, i;
4226     const char *query;
4227     UINT r;
4228
4229     /* just MsiOpenDatabase should not create a file */
4230     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4231     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4232
4233     /* create a table */
4234     query = "CREATE TABLE `integers` ( "
4235             "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4236             "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4237             "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4238             "PRIMARY KEY `one`)";
4239     r = MsiDatabaseOpenView(hdb, query, &view);
4240     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4241     r = MsiViewExecute(view, 0);
4242     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4243     r = MsiViewClose(view);
4244     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4245     r = MsiCloseHandle(view);
4246     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4247
4248     query = "SELECT * FROM `integers`";
4249     r = MsiDatabaseOpenView(hdb, query, &view);
4250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4251
4252     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4254     count = MsiRecordGetFieldCount(rec);
4255     ok(count == 8, "Expected 8, got %d\n", count);
4256     ok(check_record(rec, 1, "one"), "Expected one\n");
4257     ok(check_record(rec, 2, "two"), "Expected two\n");
4258     ok(check_record(rec, 3, "three"), "Expected three\n");
4259     ok(check_record(rec, 4, "four"), "Expected four\n");
4260     ok(check_record(rec, 5, "five"), "Expected five\n");
4261     ok(check_record(rec, 6, "six"), "Expected six\n");
4262     ok(check_record(rec, 7, "seven"), "Expected seven\n");
4263     ok(check_record(rec, 8, "eight"), "Expected eight\n");
4264     MsiCloseHandle(rec);
4265
4266     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4268     count = MsiRecordGetFieldCount(rec);
4269     ok(count == 8, "Expected 8, got %d\n", count);
4270     ok(check_record(rec, 1, "I2"), "Expected I2\n");
4271     ok(check_record(rec, 2, "I2"), "Expected I2\n");
4272     ok(check_record(rec, 3, "I2"), "Expected I2\n");
4273     ok(check_record(rec, 4, "I4"), "Expected I4\n");
4274     ok(check_record(rec, 5, "i2"), "Expected i2\n");
4275     ok(check_record(rec, 6, "i2"), "Expected i2\n");
4276     ok(check_record(rec, 7, "i2"), "Expected i2\n");
4277     ok(check_record(rec, 8, "i4"), "Expected i4\n");
4278     MsiCloseHandle(rec);
4279
4280     MsiViewClose(view);
4281     MsiCloseHandle(view);
4282
4283     /* insert values into it, NULL where NOT NULL is specified */
4284     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4285         "VALUES('', '', '', '', '', '', '', '')";
4286     r = MsiDatabaseOpenView(hdb, query, &view);
4287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4288     r = MsiViewExecute(view, 0);
4289     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4290
4291     MsiViewClose(view);
4292     MsiCloseHandle(view);
4293
4294     query = "SELECT * FROM `integers`";
4295     r = do_query(hdb, query, &rec);
4296     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4297
4298     r = MsiRecordGetFieldCount(rec);
4299     ok(r == -1, "record count wrong: %d\n", r);
4300
4301     MsiCloseHandle(rec);
4302
4303     /* insert legitimate values into it */
4304     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4305         "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4306     r = MsiDatabaseOpenView(hdb, query, &view);
4307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4308     r = MsiViewExecute(view, 0);
4309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4310
4311     query = "SELECT * FROM `integers`";
4312     r = do_query(hdb, query, &rec);
4313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4314
4315     r = MsiRecordGetFieldCount(rec);
4316     ok(r == 8, "record count wrong: %d\n", r);
4317
4318     i = MsiRecordGetInteger(rec, 1);
4319     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4320     i = MsiRecordGetInteger(rec, 3);
4321     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4322     i = MsiRecordGetInteger(rec, 2);
4323     ok(i == 2, "Expected 2, got %d\n", i);
4324     i = MsiRecordGetInteger(rec, 4);
4325     ok(i == 4, "Expected 4, got %d\n", i);
4326     i = MsiRecordGetInteger(rec, 5);
4327     ok(i == 5, "Expected 5, got %d\n", i);
4328     i = MsiRecordGetInteger(rec, 6);
4329     ok(i == 6, "Expected 6, got %d\n", i);
4330     i = MsiRecordGetInteger(rec, 7);
4331     ok(i == 7, "Expected 7, got %d\n", i);
4332     i = MsiRecordGetInteger(rec, 8);
4333     ok(i == 8, "Expected 8, got %d\n", i);
4334
4335     MsiCloseHandle(rec);
4336     MsiViewClose(view);
4337     MsiCloseHandle(view);
4338
4339     r = MsiDatabaseCommit(hdb);
4340     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4341
4342     r = MsiCloseHandle(hdb);
4343     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4344
4345     r = DeleteFile(msifile);
4346     ok(r == TRUE, "file didn't exist after commit\n");
4347 }
4348
4349 static void test_update(void)
4350 {
4351     MSIHANDLE hdb = 0, view = 0, rec = 0;
4352     CHAR result[MAX_PATH];
4353     const char *query;
4354     DWORD size;
4355     UINT r;
4356
4357     /* just MsiOpenDatabase should not create a file */
4358     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4359     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4360
4361     /* create the Control table */
4362     query = "CREATE TABLE `Control` ( "
4363         "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4364         "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4365         "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4366         "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4367     r = MsiDatabaseOpenView(hdb, query, &view);
4368     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4369     r = MsiViewExecute(view, 0);
4370     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4371     r = MsiViewClose(view);
4372     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4373     r = MsiCloseHandle(view);
4374     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4375
4376     /* add a control */
4377     query = "INSERT INTO `Control` ( "
4378         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4379         "`Property`, `Text`, `Control_Next`, `Help` )"
4380         "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4381     r = MsiDatabaseOpenView(hdb, query, &view);
4382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4383     r = MsiViewExecute(view, 0);
4384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4385     r = MsiViewClose(view);
4386     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4387     r = MsiCloseHandle(view);
4388     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4389
4390     /* add a second control */
4391     query = "INSERT INTO `Control` ( "
4392         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4393         "`Property`, `Text`, `Control_Next`, `Help` )"
4394         "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4395     r = MsiDatabaseOpenView(hdb, query, &view);
4396     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4397     r = MsiViewExecute(view, 0);
4398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4399     r = MsiViewClose(view);
4400     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4401     r = MsiCloseHandle(view);
4402     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4403
4404     /* add a third control */
4405     query = "INSERT INTO `Control` ( "
4406         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4407         "`Property`, `Text`, `Control_Next`, `Help` )"
4408         "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4409     r = MsiDatabaseOpenView(hdb, query, &view);
4410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4411     r = MsiViewExecute(view, 0);
4412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4413     r = MsiViewClose(view);
4414     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4415     r = MsiCloseHandle(view);
4416     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4417
4418     /* bad table */
4419     query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4420     r = MsiDatabaseOpenView(hdb, query, &view);
4421     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4422
4423     /* bad set column */
4424     query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4425     r = MsiDatabaseOpenView(hdb, query, &view);
4426     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4427
4428     /* bad where condition */
4429     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4430     r = MsiDatabaseOpenView(hdb, query, &view);
4431     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4432
4433     /* just the dialog_ specified */
4434     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4435     r = MsiDatabaseOpenView(hdb, query, &view);
4436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4437     r = MsiViewExecute(view, 0);
4438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4439     r = MsiViewClose(view);
4440     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4441     r = MsiCloseHandle(view);
4442     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4443
4444     /* check the modified text */
4445     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4446     r = MsiDatabaseOpenView(hdb, query, &view);
4447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4448     r = MsiViewExecute(view, 0);
4449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4450
4451     r = MsiViewFetch(view, &rec);
4452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4453
4454     size = MAX_PATH;
4455     r = MsiRecordGetString(rec, 1, result, &size);
4456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4457     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4458
4459     MsiCloseHandle(rec);
4460
4461     r = MsiViewFetch(view, &rec);
4462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4463
4464     size = MAX_PATH;
4465     r = MsiRecordGetString(rec, 1, result, &size);
4466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4467     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4468
4469     MsiCloseHandle(rec);
4470
4471     r = MsiViewFetch(view, &rec);
4472     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4473
4474     r = MsiViewClose(view);
4475     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4476     r = MsiCloseHandle(view);
4477     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4478
4479     /* dialog_ and control specified */
4480     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4481     r = MsiDatabaseOpenView(hdb, query, &view);
4482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4483     r = MsiViewExecute(view, 0);
4484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4485     r = MsiViewClose(view);
4486     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4487     r = MsiCloseHandle(view);
4488     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4489
4490     /* check the modified text */
4491     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4492     r = MsiDatabaseOpenView(hdb, query, &view);
4493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4494     r = MsiViewExecute(view, 0);
4495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4496
4497     r = MsiViewFetch(view, &rec);
4498     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4499
4500     size = MAX_PATH;
4501     r = MsiRecordGetString(rec, 1, result, &size);
4502     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4503     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4504
4505     MsiCloseHandle(rec);
4506
4507     r = MsiViewFetch(view, &rec);
4508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4509
4510     size = MAX_PATH;
4511     r = MsiRecordGetString(rec, 1, result, &size);
4512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4513     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4514
4515     MsiCloseHandle(rec);
4516
4517     r = MsiViewFetch(view, &rec);
4518     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4519
4520     r = MsiViewClose(view);
4521     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4522     r = MsiCloseHandle(view);
4523     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4524
4525     /* no where condition */
4526     query = "UPDATE `Control` SET `Text` = 'this is text'";
4527     r = MsiDatabaseOpenView(hdb, query, &view);
4528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4529     r = MsiViewExecute(view, 0);
4530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4531     r = MsiViewClose(view);
4532     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4533     r = MsiCloseHandle(view);
4534     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4535
4536     /* check the modified text */
4537     query = "SELECT `Text` FROM `Control`";
4538     r = MsiDatabaseOpenView(hdb, query, &view);
4539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4540     r = MsiViewExecute(view, 0);
4541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4542
4543     r = MsiViewFetch(view, &rec);
4544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4545
4546     size = MAX_PATH;
4547     r = MsiRecordGetString(rec, 1, result, &size);
4548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4549     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4550
4551     MsiCloseHandle(rec);
4552
4553     r = MsiViewFetch(view, &rec);
4554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4555
4556     size = MAX_PATH;
4557     r = MsiRecordGetString(rec, 1, result, &size);
4558     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4559     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4560
4561     MsiCloseHandle(rec);
4562
4563     r = MsiViewFetch(view, &rec);
4564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4565
4566     size = MAX_PATH;
4567     r = MsiRecordGetString(rec, 1, result, &size);
4568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4569     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4570
4571     MsiCloseHandle(rec);
4572
4573     r = MsiViewFetch(view, &rec);
4574     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4575
4576     r = MsiViewClose(view);
4577     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4578     r = MsiCloseHandle(view);
4579     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4580
4581     query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4582         "`Orange` CHAR(72),  `Pear` INT PRIMARY KEY `Banana`)";
4583     r = run_query(hdb, 0, query);
4584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4585
4586     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4587         "VALUES('one', 'two', 3)";
4588     r = run_query(hdb, 0, query);
4589     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4590
4591     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4592         "VALUES('three', 'four', 5)";
4593     r = run_query(hdb, 0, query);
4594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4595
4596     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4597         "VALUES('six', 'two', 7)";
4598     r = run_query(hdb, 0, query);
4599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4600
4601     rec = MsiCreateRecord(2);
4602     MsiRecordSetInteger(rec, 1, 8);
4603     MsiRecordSetString(rec, 2, "two");
4604
4605     query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4606     r = run_query(hdb, rec, query);
4607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4608
4609     MsiCloseHandle(rec);
4610
4611     query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4612     r = MsiDatabaseOpenView(hdb, query, &view);
4613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4614     r = MsiViewExecute(view, 0);
4615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616
4617     r = MsiViewFetch(view, &rec);
4618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4619
4620     r = MsiRecordGetInteger(rec, 1);
4621     ok(r == 8, "Expected 8, got %d\n", r);
4622
4623     MsiCloseHandle(rec);
4624
4625     r = MsiViewFetch(view, &rec);
4626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4627
4628     r = MsiRecordGetInteger(rec, 1);
4629     ok(r == 8, "Expected 8, got %d\n", r);
4630
4631     MsiCloseHandle(rec);
4632
4633     r = MsiViewFetch(view, &rec);
4634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4635
4636     r = MsiRecordGetInteger(rec, 1);
4637     ok(r == 5, "Expected 5, got %d\n", r);
4638
4639     MsiCloseHandle(rec);
4640
4641     r = MsiViewFetch(view, &rec);
4642     ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4643
4644     MsiViewClose(view);
4645     MsiCloseHandle(view);
4646
4647     r = MsiDatabaseCommit(hdb);
4648     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4649     r = MsiCloseHandle(hdb);
4650     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4651
4652     DeleteFile(msifile);
4653 }
4654
4655 static void test_special_tables(void)
4656 {
4657     const char *query;
4658     MSIHANDLE hdb = 0;
4659     UINT r;
4660
4661     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4662     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4663
4664     query = "CREATE TABLE `_Properties` ( "
4665         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4666     r = run_query(hdb, 0, query);
4667     ok(r == ERROR_SUCCESS, "failed to create table\n");
4668
4669     query = "CREATE TABLE `_Storages` ( "
4670         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4671     r = run_query(hdb, 0, query);
4672     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4673
4674     query = "CREATE TABLE `_Streams` ( "
4675         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4676     r = run_query(hdb, 0, query);
4677     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4678
4679     query = "CREATE TABLE `_Tables` ( "
4680         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4681     r = run_query(hdb, 0, query);
4682     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4683
4684     query = "CREATE TABLE `_Columns` ( "
4685         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4686     r = run_query(hdb, 0, query);
4687     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4688
4689     r = MsiCloseHandle(hdb);
4690     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4691 }
4692
4693 static void test_tables_order(void)
4694 {
4695     const char *query;
4696     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4697     UINT r;
4698     char buffer[100];
4699     DWORD sz;
4700
4701     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4702     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4703
4704     query = "CREATE TABLE `foo` ( "
4705         "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4706     r = run_query(hdb, 0, query);
4707     ok(r == ERROR_SUCCESS, "failed to create table\n");
4708
4709     query = "CREATE TABLE `bar` ( "
4710         "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4711     r = run_query(hdb, 0, query);
4712     ok(r == ERROR_SUCCESS, "failed to create table\n");
4713
4714     query = "CREATE TABLE `baz` ( "
4715         "`bar` INT NOT NULL, "
4716         "`baz` INT NOT NULL, "
4717         "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4718     r = run_query(hdb, 0, query);
4719     ok(r == ERROR_SUCCESS, "failed to create table\n");
4720
4721     /* The names of the tables in the _Tables table must
4722        be in the same order as these names are created in
4723        the strings table. */
4724     query = "SELECT * FROM `_Tables`";
4725     r = MsiDatabaseOpenView(hdb, query, &hview);
4726     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4727     r = MsiViewExecute(hview, 0);
4728     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4729
4730     r = MsiViewFetch(hview, &hrec);
4731     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4732     sz = sizeof(buffer);
4733     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4735     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4736     r = MsiCloseHandle(hrec);
4737     ok(r == ERROR_SUCCESS, "failed to close record\n");
4738
4739     r = MsiViewFetch(hview, &hrec);
4740     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4741     sz = sizeof(buffer);
4742     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4744     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4745     r = MsiCloseHandle(hrec);
4746     ok(r == ERROR_SUCCESS, "failed to close record\n");
4747
4748     r = MsiViewFetch(hview, &hrec);
4749     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4750     sz = sizeof(buffer);
4751     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4753     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4754     r = MsiCloseHandle(hrec);
4755     ok(r == ERROR_SUCCESS, "failed to close record\n");
4756
4757     r = MsiViewClose(hview);
4758     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4759     r = MsiCloseHandle(hview);
4760     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4761
4762     /* The names of the tables in the _Columns table must
4763        be in the same order as these names are created in
4764        the strings table. */
4765     query = "SELECT * FROM `_Columns`";
4766     r = MsiDatabaseOpenView(hdb, query, &hview);
4767     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4768     r = MsiViewExecute(hview, 0);
4769     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4770
4771     r = MsiViewFetch(hview, &hrec);
4772     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4773     sz = sizeof(buffer);
4774     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4776     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4777     sz = sizeof(buffer);
4778     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4780     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4781     r = MsiCloseHandle(hrec);
4782     ok(r == ERROR_SUCCESS, "failed to close record\n");
4783
4784     r = MsiViewFetch(hview, &hrec);
4785     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4786     sz = sizeof(buffer);
4787     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4789     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4790     sz = sizeof(buffer);
4791     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4793     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4794     r = MsiCloseHandle(hrec);
4795     ok(r == ERROR_SUCCESS, "failed to close record\n");
4796
4797     r = MsiViewFetch(hview, &hrec);
4798     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4799     sz = sizeof(buffer);
4800     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4802     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4803     sz = sizeof(buffer);
4804     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4806     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4807     r = MsiCloseHandle(hrec);
4808     ok(r == ERROR_SUCCESS, "failed to close record\n");
4809
4810     r = MsiViewFetch(hview, &hrec);
4811     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4812     sz = sizeof(buffer);
4813     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4815     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4816     sz = sizeof(buffer);
4817     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4818     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4819     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4820     r = MsiCloseHandle(hrec);
4821     ok(r == ERROR_SUCCESS, "failed to close record\n");
4822
4823     r = MsiViewFetch(hview, &hrec);
4824     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4825     sz = sizeof(buffer);
4826     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4828     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4829     sz = sizeof(buffer);
4830     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4832     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4833     r = MsiCloseHandle(hrec);
4834     ok(r == ERROR_SUCCESS, "failed to close record\n");
4835
4836     r = MsiViewClose(hview);
4837     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4838     r = MsiCloseHandle(hview);
4839     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4840
4841     r = MsiCloseHandle(hdb);
4842     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4843
4844     DeleteFile(msifile);
4845 }
4846
4847 static void test_rows_order(void)
4848 {
4849     const char *query;
4850     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4851     UINT r;
4852     char buffer[100];
4853     DWORD sz;
4854
4855     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4856     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4857
4858     query = "CREATE TABLE `foo` ( "
4859         "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4860     r = run_query(hdb, 0, query);
4861     ok(r == ERROR_SUCCESS, "failed to create table\n");
4862
4863     r = run_query(hdb, 0, "INSERT INTO `foo` "
4864             "( `bar` ) VALUES ( 'A' )");
4865     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4866
4867     r = run_query(hdb, 0, "INSERT INTO `foo` "
4868             "( `bar` ) VALUES ( 'B' )");
4869     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4870
4871     r = run_query(hdb, 0, "INSERT INTO `foo` "
4872             "( `bar` ) VALUES ( 'C' )");
4873     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4874
4875     r = run_query(hdb, 0, "INSERT INTO `foo` "
4876             "( `bar` ) VALUES ( 'D' )");
4877     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4878
4879     r = run_query(hdb, 0, "INSERT INTO `foo` "
4880             "( `bar` ) VALUES ( 'E' )");
4881     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4882
4883     r = run_query(hdb, 0, "INSERT INTO `foo` "
4884             "( `bar` ) VALUES ( 'F' )");
4885     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4886
4887     query = "CREATE TABLE `bar` ( "
4888         "`foo` LONGCHAR NOT NULL, "
4889         "`baz` LONGCHAR NOT NULL "
4890         "PRIMARY KEY `foo` )";
4891     r = run_query(hdb, 0, query);
4892     ok(r == ERROR_SUCCESS, "failed to create table\n");
4893
4894     r = run_query(hdb, 0, "INSERT INTO `bar` "
4895             "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4896     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4897
4898     r = run_query(hdb, 0, "INSERT INTO `bar` "
4899             "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4900     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4901
4902     r = run_query(hdb, 0, "INSERT INTO `bar` "
4903             "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4904     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4905
4906     r = run_query(hdb, 0, "INSERT INTO `bar` "
4907             "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4908     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4909
4910     /* The rows of the table must be ordered by the column values of
4911        each row. For strings, the column value is the string id
4912        in the string table.  */
4913
4914     query = "SELECT * FROM `bar`";
4915     r = MsiDatabaseOpenView(hdb, query, &hview);
4916     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4917     r = MsiViewExecute(hview, 0);
4918     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4919
4920     r = MsiViewFetch(hview, &hrec);
4921     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4922     sz = sizeof(buffer);
4923     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4925     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4926     sz = sizeof(buffer);
4927     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4929     ok(!lstrcmp(buffer, "B"), "Expected B, got %s\n", buffer);
4930     r = MsiCloseHandle(hrec);
4931     ok(r == ERROR_SUCCESS, "failed to close record\n");
4932
4933     r = MsiViewFetch(hview, &hrec);
4934     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4935     sz = sizeof(buffer);
4936     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4938     ok(!lstrcmp(buffer, "C"), "Expected E, got %s\n", buffer);
4939     sz = sizeof(buffer);
4940     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4942     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4943     r = MsiCloseHandle(hrec);
4944     ok(r == ERROR_SUCCESS, "failed to close record\n");
4945
4946     r = MsiViewFetch(hview, &hrec);
4947     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4948     sz = sizeof(buffer);
4949     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4951     ok(!lstrcmp(buffer, "D"), "Expected D, got %s\n", buffer);
4952     sz = sizeof(buffer);
4953     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4955     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4956     r = MsiCloseHandle(hrec);
4957     ok(r == ERROR_SUCCESS, "failed to close record\n");
4958
4959     r = MsiViewFetch(hview, &hrec);
4960     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4961     sz = sizeof(buffer);
4962     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4964     ok(!lstrcmp(buffer, "F"), "Expected F, got %s\n", buffer);
4965     sz = sizeof(buffer);
4966     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4968     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4969     r = MsiCloseHandle(hrec);
4970     ok(r == ERROR_SUCCESS, "failed to close record\n");
4971
4972     r = MsiViewClose(hview);
4973     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4974     r = MsiCloseHandle(hview);
4975     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4976
4977     r = MsiCloseHandle(hdb);
4978     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4979
4980     DeleteFile(msifile);
4981 }
4982
4983 static void test_collation(void)
4984 {
4985     static const WCHAR query1[] =
4986         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
4987          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
4988          '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
4989     static const WCHAR query2[] =
4990         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
4991          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
4992          '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
4993     static const WCHAR query3[] =
4994         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
4995          '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
4996            ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
4997            'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
4998     static const WCHAR query4[] =
4999         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
5000          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5001          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5002     static const WCHAR query5[] =
5003         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
5004          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5005          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5006     static const WCHAR query6[] =
5007         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
5008          ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
5009     static const WCHAR letter_C[] = {'C',0};
5010     static const WCHAR letter_D[] = {'D',0};
5011     static const WCHAR letter_a_ring[] = {'a',0x30a,0};
5012     static const WCHAR letter_a_with_ring[] = {0xe5,0};
5013     const char *query;
5014     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5015     UINT r;
5016     char buffer[100];
5017     WCHAR bufferW[100];
5018     DWORD sz;
5019
5020     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5021     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5022
5023     query = "CREATE TABLE `bar` ( "
5024         "`foo` LONGCHAR NOT NULL, "
5025         "`baz` LONGCHAR NOT NULL "
5026         "PRIMARY KEY `foo` )";
5027     r = run_query(hdb, 0, query);
5028     ok(r == ERROR_SUCCESS, "failed to create table\n");
5029
5030     r = run_query(hdb, 0, query);
5031     ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
5032
5033     r = run_query(hdb, 0, "INSERT INTO `bar` "
5034             "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
5035     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5036
5037     r = run_query(hdb, 0, "INSERT INTO `bar` "
5038             "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
5039     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5040
5041     r = run_queryW(hdb, 0, query1);
5042     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5043
5044     r = run_queryW(hdb, 0, query2);
5045     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5046
5047     r = run_queryW(hdb, 0, query3);
5048     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5049
5050     r = run_queryW(hdb, 0, query4);
5051     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5052
5053     r = run_queryW(hdb, 0, query5);
5054     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5055
5056     query = "SELECT * FROM `bar`";
5057     r = MsiDatabaseOpenView(hdb, query, &hview);
5058     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5059     r = MsiViewExecute(hview, 0);
5060     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5061
5062     r = MsiViewFetch(hview, &hrec);
5063     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5064     sz = sizeof(buffer);
5065     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5066     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5067     ok(!lstrcmp(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
5068     sz = sizeof(buffer);
5069     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5071     ok(!lstrcmp(buffer, "A"), "Expected A, got '%s'\n", buffer);
5072     MsiCloseHandle(hrec);
5073
5074     r = MsiViewFetch(hview, &hrec);
5075     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5076     sz = sizeof(buffer);
5077     r = MsiRecordGetString(hrec, 1, buffer, &sz);
5078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5079     ok(!lstrcmp(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
5080     sz = sizeof(buffer);
5081     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5083     ok(!lstrcmp(buffer, "B"), "Expected B, got '%s'\n", buffer);
5084     MsiCloseHandle(hrec);
5085
5086     r = MsiViewFetch(hview, &hrec);
5087     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5088     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5089     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5091     ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)),
5092        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
5093     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5094     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5096     ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
5097     MsiCloseHandle(hrec);
5098
5099     r = MsiViewFetch(hview, &hrec);
5100     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5101     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5102     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5104     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5105        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5106     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5107     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5109     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5110     MsiCloseHandle(hrec);
5111
5112     r = MsiViewClose(hview);
5113     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5114     r = MsiCloseHandle(hview);
5115     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5116
5117     r = MsiDatabaseOpenViewW(hdb, query6, &hview);
5118     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5119     r = MsiViewExecute(hview, 0);
5120     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5121
5122     r = MsiViewFetch(hview, &hrec);
5123     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5124     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5125     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5127     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5128        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5129     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5130     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5132     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5133     MsiCloseHandle(hrec);
5134
5135     r = MsiViewFetch(hview, &hrec);
5136     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
5137
5138     r = MsiViewClose(hview);
5139     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5140     r = MsiCloseHandle(hview);
5141     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5142
5143     r = MsiCloseHandle(hdb);
5144     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5145
5146     DeleteFile(msifile);
5147 }
5148
5149 static void test_select_markers(void)
5150 {
5151     MSIHANDLE hdb = 0, rec, view, res;
5152     LPCSTR query;
5153     UINT r;
5154     DWORD size;
5155     CHAR buf[MAX_PATH];
5156
5157     hdb = create_db();
5158     ok( hdb, "failed to create db\n");
5159
5160     r = run_query(hdb, 0,
5161             "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
5162     ok(r == S_OK, "cannot create table: %d\n", r);
5163
5164     r = run_query(hdb, 0, "INSERT INTO `Table` "
5165             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
5166     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5167
5168     r = run_query(hdb, 0, "INSERT INTO `Table` "
5169             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
5170     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5171
5172     r = run_query(hdb, 0, "INSERT INTO `Table` "
5173             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
5174     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5175
5176     r = run_query(hdb, 0, "INSERT INTO `Table` "
5177             "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
5178     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5179
5180     rec = MsiCreateRecord(2);
5181     MsiRecordSetString(rec, 1, "apple");
5182     MsiRecordSetString(rec, 2, "two");
5183
5184     query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
5185     r = MsiDatabaseOpenView(hdb, query, &view);
5186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5187
5188     r = MsiViewExecute(view, rec);
5189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5190
5191     r = MsiViewFetch(view, &res);
5192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5193
5194     size = MAX_PATH;
5195     r = MsiRecordGetString(res, 1, buf, &size);
5196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5197     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5198
5199     size = MAX_PATH;
5200     r = MsiRecordGetString(res, 2, buf, &size);
5201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5202     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5203
5204     r = MsiRecordGetInteger(res, 3);
5205     ok(r == 1, "Expected 1, got %d\n", r);
5206
5207     MsiCloseHandle(res);
5208
5209     r = MsiViewFetch(view, &res);
5210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5211
5212     size = MAX_PATH;
5213     r = MsiRecordGetString(res, 1, buf, &size);
5214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5215     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5216
5217     size = MAX_PATH;
5218     r = MsiRecordGetString(res, 2, buf, &size);
5219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5220     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5221
5222     r = MsiRecordGetInteger(res, 3);
5223     ok(r == 2, "Expected 2, got %d\n", r);
5224
5225     MsiCloseHandle(res);
5226
5227     r = MsiViewFetch(view, &res);
5228     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5229
5230     MsiCloseHandle(rec);
5231     MsiViewClose(view);
5232     MsiCloseHandle(view);
5233
5234     rec = MsiCreateRecord(2);
5235     MsiRecordSetString(rec, 1, "one");
5236     MsiRecordSetInteger(rec, 2, 1);
5237
5238     query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5239     r = MsiDatabaseOpenView(hdb, query, &view);
5240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5241     r = MsiViewExecute(view, rec);
5242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5243
5244     r = MsiViewFetch(view, &res);
5245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5246
5247     size = MAX_PATH;
5248     r = MsiRecordGetString(res, 1, buf, &size);
5249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5250     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5251
5252     size = MAX_PATH;
5253     r = MsiRecordGetString(res, 2, buf, &size);
5254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5255     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5256
5257     r = MsiRecordGetInteger(res, 3);
5258     ok(r == 2, "Expected 2, got %d\n", r);
5259
5260     MsiCloseHandle(res);
5261
5262     r = MsiViewFetch(view, &res);
5263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5264
5265     size = MAX_PATH;
5266     r = MsiRecordGetString(res, 1, buf, &size);
5267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5268     ok(!lstrcmp(buf, "banana"), "Expected banana, got %s\n", buf);
5269
5270     size = MAX_PATH;
5271     r = MsiRecordGetString(res, 2, buf, &size);
5272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5273     ok(!lstrcmp(buf, "three"), "Expected three, got %s\n", buf);
5274
5275     r = MsiRecordGetInteger(res, 3);
5276     ok(r == 3, "Expected 3, got %d\n", r);
5277
5278     MsiCloseHandle(res);
5279
5280     r = MsiViewFetch(view, &res);
5281     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5282
5283     MsiCloseHandle(rec);
5284     MsiViewClose(view);
5285     MsiCloseHandle(view);
5286     MsiCloseHandle(hdb);
5287     DeleteFile(msifile);
5288 }
5289
5290 static void test_viewmodify_update(void)
5291 {
5292     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5293     UINT i, test_max, offset, count;
5294     const char *query;
5295     UINT r;
5296
5297     DeleteFile(msifile);
5298
5299     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5300     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5301
5302     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5303     r = run_query( hdb, 0, query );
5304     ok(r == ERROR_SUCCESS, "query failed\n");
5305
5306     query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5307     r = run_query( hdb, 0, query );
5308     ok(r == ERROR_SUCCESS, "query failed\n");
5309
5310     query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5311     r = run_query( hdb, 0, query );
5312     ok(r == ERROR_SUCCESS, "query failed\n");
5313
5314     query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5315     r = run_query( hdb, 0, query );
5316     ok(r == ERROR_SUCCESS, "query failed\n");
5317
5318     query = "SELECT `B` FROM `table`";
5319     r = MsiDatabaseOpenView(hdb, query, &hview);
5320     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5321     r = MsiViewExecute(hview, 0);
5322     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5323     r = MsiViewFetch(hview, &hrec);
5324     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5325
5326     r = MsiRecordSetInteger(hrec, 1, 0);
5327     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5328
5329     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5330     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5331
5332     r = MsiCloseHandle(hrec);
5333     ok(r == ERROR_SUCCESS, "failed to close record\n");
5334
5335     r = MsiViewClose(hview);
5336     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5337     r = MsiCloseHandle(hview);
5338     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5339
5340     query = "SELECT * FROM `table`";
5341     r = MsiDatabaseOpenView(hdb, query, &hview);
5342     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5343     r = MsiViewExecute(hview, 0);
5344     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5345     r = MsiViewFetch(hview, &hrec);
5346     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5347
5348     r = MsiRecordGetInteger(hrec, 1);
5349     ok(r == 1, "Expected 1, got %d\n", r);
5350     r = MsiRecordGetInteger(hrec, 2);
5351     ok(r == 0, "Expected 0, got %d\n", r);
5352
5353     r = MsiCloseHandle(hrec);
5354     ok(r == ERROR_SUCCESS, "failed to close record\n");
5355
5356     r = MsiViewFetch(hview, &hrec);
5357     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5358
5359     r = MsiRecordGetInteger(hrec, 1);
5360     ok(r == 3, "Expected 3, got %d\n", r);
5361     r = MsiRecordGetInteger(hrec, 2);
5362     ok(r == 4, "Expected 4, got %d\n", r);
5363
5364     r = MsiCloseHandle(hrec);
5365     ok(r == ERROR_SUCCESS, "failed to close record\n");
5366
5367     r = MsiViewFetch(hview, &hrec);
5368     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5369
5370     r = MsiRecordGetInteger(hrec, 1);
5371     ok(r == 5, "Expected 5, got %d\n", r);
5372     r = MsiRecordGetInteger(hrec, 2);
5373     ok(r == 6, "Expected 6, got %d\n", r);
5374
5375     r = MsiCloseHandle(hrec);
5376     ok(r == ERROR_SUCCESS, "failed to close record\n");
5377
5378     r = MsiViewFetch(hview, &hrec);
5379     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5380
5381     r = MsiViewClose(hview);
5382     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5383     r = MsiCloseHandle(hview);
5384     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5385
5386     /* loop through all elements */
5387     query = "SELECT `B` FROM `table`";
5388     r = MsiDatabaseOpenView(hdb, query, &hview);
5389     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5390     r = MsiViewExecute(hview, 0);
5391     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5392
5393     while (TRUE)
5394     {
5395         r = MsiViewFetch(hview, &hrec);
5396         if (r != ERROR_SUCCESS)
5397             break;
5398
5399         r = MsiRecordSetInteger(hrec, 1, 0);
5400         ok(r == ERROR_SUCCESS, "failed to set integer\n");
5401
5402         r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5403         ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5404
5405         r = MsiCloseHandle(hrec);
5406         ok(r == ERROR_SUCCESS, "failed to close record\n");
5407     }
5408
5409     r = MsiViewClose(hview);
5410     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5411     r = MsiCloseHandle(hview);
5412     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5413
5414     query = "SELECT * FROM `table`";
5415     r = MsiDatabaseOpenView(hdb, query, &hview);
5416     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5417     r = MsiViewExecute(hview, 0);
5418     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5419     r = MsiViewFetch(hview, &hrec);
5420     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5421
5422     r = MsiRecordGetInteger(hrec, 1);
5423     ok(r == 1, "Expected 1, got %d\n", r);
5424     r = MsiRecordGetInteger(hrec, 2);
5425     ok(r == 0, "Expected 0, got %d\n", r);
5426
5427     r = MsiCloseHandle(hrec);
5428     ok(r == ERROR_SUCCESS, "failed to close record\n");
5429
5430     r = MsiViewFetch(hview, &hrec);
5431     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5432
5433     r = MsiRecordGetInteger(hrec, 1);
5434     ok(r == 3, "Expected 3, got %d\n", r);
5435     r = MsiRecordGetInteger(hrec, 2);
5436     ok(r == 0, "Expected 0, got %d\n", r);
5437
5438     r = MsiCloseHandle(hrec);
5439     ok(r == ERROR_SUCCESS, "failed to close record\n");
5440
5441     r = MsiViewFetch(hview, &hrec);
5442     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5443
5444     r = MsiRecordGetInteger(hrec, 1);
5445     ok(r == 5, "Expected 5, got %d\n", r);
5446     r = MsiRecordGetInteger(hrec, 2);
5447     ok(r == 0, "Expected 0, got %d\n", r);
5448
5449     r = MsiCloseHandle(hrec);
5450     ok(r == ERROR_SUCCESS, "failed to close record\n");
5451
5452     r = MsiViewFetch(hview, &hrec);
5453     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5454
5455     r = MsiViewClose(hview);
5456     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5457     r = MsiCloseHandle(hview);
5458     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5459
5460     query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5461     r = run_query( hdb, 0, query );
5462     ok(r == ERROR_SUCCESS, "query failed\n");
5463
5464     query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5465     r = MsiDatabaseOpenView( hdb, query, &hview );
5466     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5467
5468     test_max = 100;
5469     offset = 1234;
5470     for(i = 0; i < test_max; i++)
5471     {
5472
5473         hrec = MsiCreateRecord( 2 );
5474         MsiRecordSetInteger( hrec, 1, test_max - i );
5475         MsiRecordSetInteger( hrec, 2, i );
5476
5477         r = MsiViewExecute( hview, hrec );
5478         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5479
5480         r = MsiCloseHandle( hrec );
5481         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5482     }
5483
5484     r = MsiViewClose( hview );
5485     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5486     r = MsiCloseHandle( hview );
5487     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5488
5489     /* Update. */
5490     query = "SELECT * FROM `table2` ORDER BY `B`";
5491     r = MsiDatabaseOpenView( hdb, query, &hview);
5492     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5493     r = MsiViewExecute( hview, 0 );
5494     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5495
5496     count = 0;
5497     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5498     {
5499         UINT b = MsiRecordGetInteger( hrec, 2 );
5500
5501         r = MsiRecordSetInteger( hrec, 2, b + offset);
5502         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5503
5504         r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5505         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5506
5507         r = MsiCloseHandle(hrec);
5508         ok(r == ERROR_SUCCESS, "failed to close record\n");
5509         count++;
5510     }
5511     ok(count == test_max, "Got count %d\n", count);
5512
5513     r = MsiViewClose(hview);
5514     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5515     r = MsiCloseHandle(hview);
5516     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5517
5518     /* Recheck. */
5519     query = "SELECT * FROM `table2` ORDER BY `B`";
5520     r = MsiDatabaseOpenView( hdb, query, &hview);
5521     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5522     r = MsiViewExecute( hview, 0 );
5523     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5524
5525     count = 0;
5526     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5527     {
5528         UINT a = MsiRecordGetInteger( hrec, 1 );
5529         UINT b = MsiRecordGetInteger( hrec, 2 );
5530         ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5531             a, b, test_max - a + offset, b);
5532
5533         r = MsiCloseHandle(hrec);
5534         ok(r == ERROR_SUCCESS, "failed to close record\n");
5535         count++;
5536     }
5537     ok(count == test_max, "Got count %d\n", count);
5538
5539     r = MsiViewClose(hview);
5540     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5541     r = MsiCloseHandle(hview);
5542     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5543
5544     r = MsiCloseHandle( hdb );
5545     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5546 }
5547
5548 static void test_viewmodify_assign(void)
5549 {
5550     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5551     const char *query;
5552     UINT r;
5553
5554     /* setup database */
5555     DeleteFile(msifile);
5556
5557     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5558     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5559
5560     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5561     r = run_query( hdb, 0, query );
5562     ok(r == ERROR_SUCCESS, "query failed\n");
5563
5564     /* assign to view, new primary key */
5565     query = "SELECT * FROM `table`";
5566     r = MsiDatabaseOpenView(hdb, query, &hview);
5567     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5568     r = MsiViewExecute(hview, 0);
5569     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5570
5571     hrec = MsiCreateRecord(2);
5572     ok(hrec != 0, "MsiCreateRecord failed\n");
5573
5574     r = MsiRecordSetInteger(hrec, 1, 1);
5575     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5576     r = MsiRecordSetInteger(hrec, 2, 2);
5577     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5578
5579     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5580     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5581
5582     r = MsiCloseHandle(hrec);
5583     ok(r == ERROR_SUCCESS, "failed to close record\n");
5584
5585     r = MsiViewClose(hview);
5586     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5587     r = MsiCloseHandle(hview);
5588     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5589
5590     query = "SELECT * FROM `table`";
5591     r = MsiDatabaseOpenView(hdb, query, &hview);
5592     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5593     r = MsiViewExecute(hview, 0);
5594     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5595     r = MsiViewFetch(hview, &hrec);
5596     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5597
5598     r = MsiRecordGetInteger(hrec, 1);
5599     ok(r == 1, "Expected 1, got %d\n", r);
5600     r = MsiRecordGetInteger(hrec, 2);
5601     ok(r == 2, "Expected 2, got %d\n", r);
5602
5603     r = MsiCloseHandle(hrec);
5604     ok(r == ERROR_SUCCESS, "failed to close record\n");
5605
5606     r = MsiViewFetch(hview, &hrec);
5607     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5608
5609     r = MsiViewClose(hview);
5610     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5611     r = MsiCloseHandle(hview);
5612     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5613
5614     /* assign to view, primary key matches */
5615     query = "SELECT * FROM `table`";
5616     r = MsiDatabaseOpenView(hdb, query, &hview);
5617     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5618     r = MsiViewExecute(hview, 0);
5619     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5620
5621     hrec = MsiCreateRecord(2);
5622     ok(hrec != 0, "MsiCreateRecord failed\n");
5623
5624     r = MsiRecordSetInteger(hrec, 1, 1);
5625     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5626     r = MsiRecordSetInteger(hrec, 2, 4);
5627     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5628
5629     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5630     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5631
5632     r = MsiCloseHandle(hrec);
5633     ok(r == ERROR_SUCCESS, "failed to close record\n");
5634
5635     r = MsiViewClose(hview);
5636     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5637     r = MsiCloseHandle(hview);
5638     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5639
5640     query = "SELECT * FROM `table`";
5641     r = MsiDatabaseOpenView(hdb, query, &hview);
5642     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5643     r = MsiViewExecute(hview, 0);
5644     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5645     r = MsiViewFetch(hview, &hrec);
5646     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5647
5648     r = MsiRecordGetInteger(hrec, 1);
5649     ok(r == 1, "Expected 1, got %d\n", r);
5650     r = MsiRecordGetInteger(hrec, 2);
5651     ok(r == 4, "Expected 4, got %d\n", r);
5652
5653     r = MsiCloseHandle(hrec);
5654     ok(r == ERROR_SUCCESS, "failed to close record\n");
5655
5656     r = MsiViewFetch(hview, &hrec);
5657     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5658
5659     r = MsiViewClose(hview);
5660     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5661     r = MsiCloseHandle(hview);
5662     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5663
5664     /* close database */
5665     r = MsiCloseHandle( hdb );
5666     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5667 }
5668
5669 static const WCHAR data10[] = { /* MOO */
5670     0x8001, 0x000b,
5671 };
5672 static const WCHAR data11[] = { /* AAR */
5673     0x8002, 0x8005,
5674     0x000c, 0x000f,
5675 };
5676 static const char data12[] = /* _StringData */
5677     "MOOABAARCDonetwofourfive";
5678 static const WCHAR data13[] = { /* _StringPool */
5679 /*  len, refs */
5680     0,   0,    /* string 0 ''     */
5681     0,   0,    /* string 1 ''     */
5682     0,   0,    /* string 2 ''     */
5683     0,   0,    /* string 3 ''     */
5684     0,   0,    /* string 4 ''     */
5685     3,   3,    /* string 5 'MOO'  */
5686     1,   1,    /* string 6 'A'    */
5687     1,   1,    /* string 7 'B'    */
5688     3,   3,    /* string 8 'AAR'  */
5689     1,   1,    /* string 9 'C'    */
5690     1,   1,    /* string a 'D'    */
5691     3,   1,    /* string b 'one'  */
5692     3,   1,    /* string c 'two'  */
5693     0,   0,    /* string d ''     */
5694     4,   1,    /* string e 'four' */
5695     4,   1,    /* string f 'five' */
5696 };
5697
5698 static void test_stringtable(void)
5699 {
5700     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5701     IStorage *stg = NULL;
5702     IStream *stm;
5703     WCHAR name[0x20];
5704     HRESULT hr;
5705     const char *query;
5706     char buffer[MAX_PATH];
5707     WCHAR data[MAX_PATH];
5708     DWORD sz, read;
5709     UINT r;
5710
5711     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5712     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5713     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5714     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5715     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5716
5717     DeleteFile(msifile);
5718
5719     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5721
5722     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5723     r = run_query(hdb, 0, query);
5724     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5725
5726     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5727     r = run_query(hdb, 0, query);
5728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5729
5730     /* insert persistent row */
5731     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5732     r = run_query(hdb, 0, query);
5733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5734
5735     /* insert persistent row */
5736     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5737     r = run_query(hdb, 0, query);
5738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5739
5740     /* open a view */
5741     query = "SELECT * FROM `MOO`";
5742     r = MsiDatabaseOpenView(hdb, query, &hview);
5743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5744     r = MsiViewExecute(hview, 0);
5745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5746
5747     hrec = MsiCreateRecord(2);
5748
5749     r = MsiRecordSetInteger(hrec, 1, 3);
5750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5751     r = MsiRecordSetString(hrec, 2, "three");
5752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5753
5754     /* insert a nonpersistent row */
5755     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5757
5758     r = MsiCloseHandle(hrec);
5759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5760     r = MsiViewClose(hview);
5761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5762     r = MsiCloseHandle(hview);
5763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5764
5765     /* insert persistent row */
5766     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5767     r = run_query(hdb, 0, query);
5768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5769
5770     /* insert persistent row */
5771     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5772     r = run_query(hdb, 0, query);
5773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5774
5775     r = MsiDatabaseCommit(hdb);
5776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5777
5778     r = MsiCloseHandle(hdb);
5779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5780
5781     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
5782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5783
5784     query = "SELECT * FROM `MOO`";
5785     r = MsiDatabaseOpenView(hdb, query, &hview);
5786     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5787
5788     r = MsiViewExecute(hview, 0);
5789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5790
5791     r = MsiViewFetch(hview, &hrec);
5792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5793
5794     r = MsiRecordGetFieldCount(hrec);
5795     ok(r == 2, "Expected 2, got %d\n", r);
5796
5797     r = MsiRecordGetInteger(hrec, 1);
5798     ok(r == 1, "Expected 1, got %d\n", r);
5799
5800     sz = sizeof(buffer);
5801     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5803     ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
5804
5805     r = MsiCloseHandle(hrec);
5806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5807
5808     r = MsiViewFetch(hview, &hrec);
5809     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5810
5811     r = MsiViewClose(hview);
5812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5813     r = MsiCloseHandle(hview);
5814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5815     r = MsiCloseHandle(hrec);
5816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5817
5818     query = "SELECT * FROM `AAR`";
5819     r = MsiDatabaseOpenView(hdb, query, &hview);
5820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5821
5822     r = MsiViewExecute(hview, 0);
5823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5824
5825     r = MsiViewFetch(hview, &hrec);
5826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5827
5828     r = MsiRecordGetFieldCount(hrec);
5829     ok(r == 2, "Expected 2, got %d\n", r);
5830
5831     r = MsiRecordGetInteger(hrec, 1);
5832     ok(r == 2, "Expected 2, got %d\n", r);
5833
5834     sz = sizeof(buffer);
5835     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5837     ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
5838
5839     r = MsiCloseHandle(hrec);
5840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5841
5842     r = MsiViewFetch(hview, &hrec);
5843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5844
5845     r = MsiRecordGetFieldCount(hrec);
5846     ok(r == 2, "Expected 2, got %d\n", r);
5847
5848     r = MsiRecordGetInteger(hrec, 1);
5849     ok(r == 5, "Expected 5, got %d\n", r);
5850
5851     sz = sizeof(buffer);
5852     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5854     ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
5855
5856     r = MsiCloseHandle(hrec);
5857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5858
5859     r = MsiViewFetch(hview, &hrec);
5860     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5861
5862     r = MsiViewClose(hview);
5863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5864     r = MsiCloseHandle(hview);
5865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5866     r = MsiCloseHandle(hrec);
5867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5868     r = MsiCloseHandle(hdb);
5869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5870
5871     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5872     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5873     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5874     ok(stg != NULL, "Expected non-NULL storage\n");
5875
5876     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5877     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5878     ok(stm != NULL, "Expected non-NULL stream\n");
5879
5880     hr = IStream_Read(stm, data, MAX_PATH, &read);
5881     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5882     ok(read == 4, "Expected 4, got %d\n", read);
5883     todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5884
5885     hr = IStream_Release(stm);
5886     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5887
5888     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5889     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5890     ok(stm != NULL, "Expected non-NULL stream\n");
5891
5892     hr = IStream_Read(stm, data, MAX_PATH, &read);
5893     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5894     ok(read == 8, "Expected 8, got %d\n", read);
5895     todo_wine
5896     {
5897         ok(!memcmp(data, data11, read), "Unexpected data\n");
5898     }
5899
5900     hr = IStream_Release(stm);
5901     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5902
5903     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5904     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5905     ok(stm != NULL, "Expected non-NULL stream\n");
5906
5907     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5908     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5909     ok(read == 24, "Expected 24, got %d\n", read);
5910     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5911
5912     hr = IStream_Release(stm);
5913     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5914
5915     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5916     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5917     ok(stm != NULL, "Expected non-NULL stream\n");
5918
5919     hr = IStream_Read(stm, data, MAX_PATH, &read);
5920     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5921     todo_wine
5922     {
5923         ok(read == 64, "Expected 64, got %d\n", read);
5924         ok(!memcmp(data, data13, read), "Unexpected data\n");
5925     }
5926
5927     hr = IStream_Release(stm);
5928     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5929
5930     hr = IStorage_Release(stg);
5931     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5932
5933     DeleteFileA(msifile);
5934 }
5935
5936 static void test_viewmodify_delete(void)
5937 {
5938     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5939     UINT r;
5940     const char *query;
5941     char buffer[0x100];
5942     DWORD sz;
5943
5944     DeleteFile(msifile);
5945
5946     /* just MsiOpenDatabase should not create a file */
5947     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5949
5950     query = "CREATE TABLE `phone` ( "
5951             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
5952             "PRIMARY KEY `id`)";
5953     r = run_query(hdb, 0, query);
5954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5955
5956     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5957         "VALUES('1', 'Alan', '5030581')";
5958     r = run_query(hdb, 0, query);
5959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5960
5961     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5962         "VALUES('2', 'Barry', '928440')";
5963     r = run_query(hdb, 0, query);
5964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5965
5966     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5967         "VALUES('3', 'Cindy', '2937550')";
5968     r = run_query(hdb, 0, query);
5969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5970
5971     query = "SELECT * FROM `phone` WHERE `id` <= 2";
5972     r = MsiDatabaseOpenView(hdb, query, &hview);
5973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5974     r = MsiViewExecute(hview, 0);
5975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5976     r = MsiViewFetch(hview, &hrec);
5977     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5978
5979     /* delete 1 */
5980     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5982
5983     r = MsiCloseHandle(hrec);
5984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5985     r = MsiViewFetch(hview, &hrec);
5986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5987
5988     /* delete 2 */
5989     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5991
5992     r = MsiCloseHandle(hrec);
5993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5994     r = MsiViewClose(hview);
5995     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5996     r = MsiCloseHandle(hview);
5997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5998
5999     query = "SELECT * FROM `phone`";
6000     r = MsiDatabaseOpenView(hdb, query, &hview);
6001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6002     r = MsiViewExecute(hview, 0);
6003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6004     r = MsiViewFetch(hview, &hrec);
6005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6006
6007     r = MsiRecordGetInteger(hrec, 1);
6008     ok(r == 3, "Expected 3, got %d\n", r);
6009
6010     sz = sizeof(buffer);
6011     r = MsiRecordGetString(hrec, 2, buffer, &sz);
6012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6013     ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
6014
6015     sz = sizeof(buffer);
6016     r = MsiRecordGetString(hrec, 3, buffer, &sz);
6017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6018     ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
6019
6020     r = MsiCloseHandle(hrec);
6021     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6022
6023     r = MsiViewFetch(hview, &hrec);
6024     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6025
6026     r = MsiViewClose(hview);
6027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6028     r = MsiCloseHandle(hview);
6029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6030     r = MsiCloseHandle(hdb);
6031     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6032 }
6033
6034 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
6035 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
6036 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
6037
6038 static const WCHAR data14[] = { /* _StringPool */
6039 /*  len, refs */
6040     0,   0,    /* string 0 ''    */
6041 };
6042
6043 static const struct {
6044     LPCWSTR name;
6045     const void *data;
6046     DWORD size;
6047 } database_table_data[] =
6048 {
6049     {_Tables, NULL, 0},
6050     {_StringData, NULL, 0},
6051     {_StringPool, data14, sizeof data14},
6052 };
6053
6054 static void enum_stream_names(IStorage *stg)
6055 {
6056     IEnumSTATSTG *stgenum = NULL;
6057     IStream *stm;
6058     HRESULT hr;
6059     STATSTG stat;
6060     ULONG n, count;
6061     BYTE data[MAX_PATH];
6062     BYTE check[MAX_PATH];
6063     DWORD sz;
6064
6065     memset(check, 'a', MAX_PATH);
6066
6067     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
6068     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6069
6070     n = 0;
6071     while(TRUE)
6072     {
6073         count = 0;
6074         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
6075         if(FAILED(hr) || !count)
6076             break;
6077
6078         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
6079            "Expected table %d name to match\n", n);
6080
6081         stm = NULL;
6082         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
6083                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6084         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6085         ok(stm != NULL, "Expected non-NULL stream\n");
6086
6087         CoTaskMemFree(stat.pwcsName);
6088
6089         sz = MAX_PATH;
6090         memset(data, 'a', MAX_PATH);
6091         hr = IStream_Read(stm, data, sz, &count);
6092         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6093
6094         ok(count == database_table_data[n].size,
6095            "Expected %d, got %d\n", database_table_data[n].size, count);
6096
6097         if (!database_table_data[n].size)
6098             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
6099         else
6100             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
6101                "Expected table %d data to match\n", n);
6102
6103         IStream_Release(stm);
6104         n++;
6105     }
6106
6107     ok(n == 3, "Expected 3, got %d\n", n);
6108
6109     IEnumSTATSTG_Release(stgenum);
6110 }
6111
6112 static void test_defaultdatabase(void)
6113 {
6114     UINT r;
6115     HRESULT hr;
6116     MSIHANDLE hdb;
6117     IStorage *stg = NULL;
6118
6119     DeleteFile(msifile);
6120
6121     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6123
6124     r = MsiDatabaseCommit(hdb);
6125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6126
6127     MsiCloseHandle(hdb);
6128
6129     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6130     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6131     ok(stg != NULL, "Expected non-NULL stg\n");
6132
6133     enum_stream_names(stg);
6134
6135     IStorage_Release(stg);
6136     DeleteFileA(msifile);
6137 }
6138
6139 static void test_order(void)
6140 {
6141     MSIHANDLE hdb, hview, hrec;
6142     CHAR buffer[MAX_PATH];
6143     LPCSTR query;
6144     UINT r, sz;
6145     int val;
6146
6147     hdb = create_db();
6148     ok(hdb, "failed to create db\n");
6149
6150     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6151     r = run_query(hdb, 0, query);
6152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6153
6154     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6155     r = run_query(hdb, 0, query);
6156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6157
6158     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6159     r = run_query(hdb, 0, query);
6160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6161
6162     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6163     r = run_query(hdb, 0, query);
6164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6165
6166     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6167     r = run_query(hdb, 0, query);
6168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6169
6170     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6171     r = run_query(hdb, 0, query);
6172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6173
6174     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6175     r = run_query(hdb, 0, query);
6176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6177
6178     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6179     r = run_query(hdb, 0, query);
6180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6181
6182     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6183     r = run_query(hdb, 0, query);
6184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6185
6186     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6187     r = MsiDatabaseOpenView(hdb, query, &hview);
6188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6189     r = MsiViewExecute(hview, 0);
6190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6191
6192     r = MsiViewFetch(hview, &hrec);
6193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6194
6195     val = MsiRecordGetInteger(hrec, 1);
6196     ok(val == 3, "Expected 3, got %d\n", val);
6197
6198     val = MsiRecordGetInteger(hrec, 2);
6199     ok(val == 4, "Expected 3, got %d\n", val);
6200
6201     MsiCloseHandle(hrec);
6202
6203     r = MsiViewFetch(hview, &hrec);
6204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6205
6206     val = MsiRecordGetInteger(hrec, 1);
6207     ok(val == 5, "Expected 5, got %d\n", val);
6208
6209     val = MsiRecordGetInteger(hrec, 2);
6210     ok(val == 6, "Expected 6, got %d\n", val);
6211
6212     MsiCloseHandle(hrec);
6213
6214     r = MsiViewFetch(hview, &hrec);
6215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6216
6217     val = MsiRecordGetInteger(hrec, 1);
6218     ok(val == 1, "Expected 1, got %d\n", val);
6219
6220     val = MsiRecordGetInteger(hrec, 2);
6221     ok(val == 2, "Expected 2, got %d\n", val);
6222
6223     MsiCloseHandle(hrec);
6224
6225     r = MsiViewFetch(hview, &hrec);
6226     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6227
6228     MsiViewClose(hview);
6229     MsiCloseHandle(hview);
6230
6231     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6232     r = MsiDatabaseOpenView(hdb, query, &hview);
6233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6234     r = MsiViewExecute(hview, 0);
6235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6236
6237     r = MsiViewFetch(hview, &hrec);
6238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6239
6240     val = MsiRecordGetInteger(hrec, 1);
6241     ok(val == 1, "Expected 1, got %d\n", val);
6242
6243     val = MsiRecordGetInteger(hrec, 2);
6244     ok(val == 12, "Expected 12, got %d\n", val);
6245
6246     MsiCloseHandle(hrec);
6247
6248     r = MsiViewFetch(hview, &hrec);
6249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6250
6251     val = MsiRecordGetInteger(hrec, 1);
6252     ok(val == 3, "Expected 3, got %d\n", val);
6253
6254     val = MsiRecordGetInteger(hrec, 2);
6255     ok(val == 12, "Expected 12, got %d\n", val);
6256
6257     MsiCloseHandle(hrec);
6258
6259     r = MsiViewFetch(hview, &hrec);
6260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6261
6262     val = MsiRecordGetInteger(hrec, 1);
6263     ok(val == 5, "Expected 5, got %d\n", val);
6264
6265     val = MsiRecordGetInteger(hrec, 2);
6266     ok(val == 12, "Expected 12, got %d\n", val);
6267
6268     MsiCloseHandle(hrec);
6269
6270     r = MsiViewFetch(hview, &hrec);
6271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6272
6273     val = MsiRecordGetInteger(hrec, 1);
6274     ok(val == 1, "Expected 1, got %d\n", val);
6275
6276     val = MsiRecordGetInteger(hrec, 2);
6277     ok(val == 14, "Expected 14, got %d\n", val);
6278
6279     MsiCloseHandle(hrec);
6280
6281     r = MsiViewFetch(hview, &hrec);
6282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6283
6284     val = MsiRecordGetInteger(hrec, 1);
6285     ok(val == 3, "Expected 3, got %d\n", val);
6286
6287     val = MsiRecordGetInteger(hrec, 2);
6288     ok(val == 14, "Expected 14, got %d\n", val);
6289
6290     MsiCloseHandle(hrec);
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 == 5, "Expected 5, got %d\n", val);
6297
6298     val = MsiRecordGetInteger(hrec, 2);
6299     ok(val == 14, "Expected 14, 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 == 1, "Expected 1, got %d\n", val);
6308
6309     val = MsiRecordGetInteger(hrec, 2);
6310     ok(val == 10, "Expected 10, 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 == 3, "Expected 3, got %d\n", val);
6319
6320     val = MsiRecordGetInteger(hrec, 2);
6321     ok(val == 10, "Expected 10, 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 == 5, "Expected 5, got %d\n", val);
6330
6331     val = MsiRecordGetInteger(hrec, 2);
6332     ok(val == 10, "Expected 10, got %d\n", val);
6333
6334     MsiCloseHandle(hrec);
6335
6336     r = MsiViewFetch(hview, &hrec);
6337     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6338
6339     MsiViewClose(hview);
6340     MsiCloseHandle(hview);
6341
6342     query = "SELECT * FROM `Empty` ORDER BY `A`";
6343     r = MsiDatabaseOpenView(hdb, query, &hview);
6344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6345     r = MsiViewExecute(hview, 0);
6346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6347
6348     r = MsiViewFetch(hview, &hrec);
6349     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6350
6351     MsiViewClose(hview);
6352     MsiCloseHandle(hview);
6353
6354     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6355     r = run_query(hdb, 0, query);
6356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6357
6358     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6359     r = run_query(hdb, 0, query);
6360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6361
6362     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6363     r = run_query(hdb, 0, query);
6364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6365
6366     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6367     r = run_query(hdb, 0, query);
6368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6369
6370     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6371     r = MsiDatabaseOpenView(hdb, query, &hview);
6372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6373     r = MsiViewExecute(hview, 0);
6374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6375
6376     r = MsiViewFetch(hview, &hrec);
6377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6378
6379     sz = sizeof(buffer);
6380     r = MsiRecordGetString(hrec, 1, buffer, &sz);
6381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6382     ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6383
6384     r = MsiRecordGetInteger(hrec, 2);
6385     ok(r == 3, "Expected 3, got %d\n", r);
6386
6387     MsiCloseHandle(hrec);
6388
6389     r = MsiViewFetch(hview, &hrec);
6390     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6391
6392     MsiViewClose(hview);
6393     MsiCloseHandle(hview);
6394     MsiCloseHandle(hdb);
6395 }
6396
6397 static void test_viewmodify_delete_temporary(void)
6398 {
6399     MSIHANDLE hdb, hview, hrec;
6400     const char *query;
6401     UINT r;
6402
6403     DeleteFile(msifile);
6404
6405     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407
6408     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6409     r = run_query(hdb, 0, query);
6410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6411
6412     query = "SELECT * FROM `Table`";
6413     r = MsiDatabaseOpenView(hdb, query, &hview);
6414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6415     r = MsiViewExecute(hview, 0);
6416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6417
6418     hrec = MsiCreateRecord(1);
6419     MsiRecordSetInteger(hrec, 1, 1);
6420
6421     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6423
6424     MsiCloseHandle(hrec);
6425
6426     hrec = MsiCreateRecord(1);
6427     MsiRecordSetInteger(hrec, 1, 2);
6428
6429     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6431
6432     MsiCloseHandle(hrec);
6433
6434     hrec = MsiCreateRecord(1);
6435     MsiRecordSetInteger(hrec, 1, 3);
6436
6437     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6439
6440     MsiCloseHandle(hrec);
6441
6442     hrec = MsiCreateRecord(1);
6443     MsiRecordSetInteger(hrec, 1, 4);
6444
6445     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6447
6448     MsiCloseHandle(hrec);
6449     MsiViewClose(hview);
6450     MsiCloseHandle(hview);
6451
6452     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6453     r = MsiDatabaseOpenView(hdb, query, &hview);
6454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6455     r = MsiViewExecute(hview, 0);
6456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6457     r = MsiViewFetch(hview, &hrec);
6458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6459
6460     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6462
6463     MsiCloseHandle(hrec);
6464     MsiViewClose(hview);
6465     MsiCloseHandle(hview);
6466
6467     query = "SELECT * FROM `Table` WHERE  `A` = 3";
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     r = MsiViewFetch(hview, &hrec);
6473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6474
6475     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6477
6478     MsiCloseHandle(hrec);
6479     MsiViewClose(hview);
6480     MsiCloseHandle(hview);
6481
6482     query = "SELECT * FROM `Table` ORDER BY `A`";
6483     r = MsiDatabaseOpenView(hdb, query, &hview);
6484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6485     r = MsiViewExecute(hview, 0);
6486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6487
6488     r = MsiViewFetch(hview, &hrec);
6489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6490
6491     r = MsiRecordGetInteger(hrec, 1);
6492     ok(r == 1, "Expected 1, got %d\n", r);
6493
6494     MsiCloseHandle(hrec);
6495
6496     r = MsiViewFetch(hview, &hrec);
6497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6498
6499     r = MsiRecordGetInteger(hrec, 1);
6500     ok(r == 4, "Expected 4, got %d\n", r);
6501
6502     MsiCloseHandle(hrec);
6503
6504     r = MsiViewFetch(hview, &hrec);
6505     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6506
6507     MsiViewClose(hview);
6508     MsiCloseHandle(hview);
6509     MsiCloseHandle(hdb);
6510     DeleteFileA(msifile);
6511 }
6512
6513 static void test_deleterow(void)
6514 {
6515     MSIHANDLE hdb, hview, hrec;
6516     const char *query;
6517     char buf[MAX_PATH];
6518     UINT r;
6519     DWORD size;
6520
6521     DeleteFile(msifile);
6522
6523     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6525
6526     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6527     r = run_query(hdb, 0, query);
6528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6529
6530     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6531     r = run_query(hdb, 0, query);
6532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6533
6534     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6535     r = run_query(hdb, 0, query);
6536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6537
6538     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6539     r = run_query(hdb, 0, query);
6540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6541
6542     r = MsiDatabaseCommit(hdb);
6543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6544
6545     MsiCloseHandle(hdb);
6546
6547     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
6548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6549
6550     query = "SELECT * FROM `Table`";
6551     r = MsiDatabaseOpenView(hdb, query, &hview);
6552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6553     r = MsiViewExecute(hview, 0);
6554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6555
6556     r = MsiViewFetch(hview, &hrec);
6557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6558
6559     size = MAX_PATH;
6560     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6562     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6563
6564     MsiCloseHandle(hrec);
6565
6566     r = MsiViewFetch(hview, &hrec);
6567     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6568
6569     MsiViewClose(hview);
6570     MsiCloseHandle(hview);
6571     MsiCloseHandle(hdb);
6572     DeleteFileA(msifile);
6573 }
6574
6575 static const CHAR import_dat[] = "A\n"
6576                                  "s72\n"
6577                                  "Table\tA\n"
6578                                  "This is a new 'string' ok\n";
6579
6580 static void test_quotes(void)
6581 {
6582     MSIHANDLE hdb, hview, hrec;
6583     const char *query;
6584     char buf[MAX_PATH];
6585     UINT r;
6586     DWORD size;
6587
6588     DeleteFile(msifile);
6589
6590     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6592
6593     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6594     r = run_query(hdb, 0, query);
6595     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6596
6597     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6598     r = run_query(hdb, 0, query);
6599     ok(r == ERROR_BAD_QUERY_SYNTAX,
6600        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6601
6602     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6603     r = run_query(hdb, 0, query);
6604     ok(r == ERROR_BAD_QUERY_SYNTAX,
6605        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6606
6607     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6608     r = run_query(hdb, 0, query);
6609     ok(r == ERROR_BAD_QUERY_SYNTAX,
6610        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6611
6612     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6613     r = run_query(hdb, 0, query);
6614     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6615
6616     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6617     r = run_query(hdb, 0, query);
6618     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6619
6620     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6621     r = run_query(hdb, 0, query);
6622     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6623
6624     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6625     r = run_query(hdb, 0, query);
6626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6627
6628     query = "SELECT * FROM `Table`";
6629     r = MsiDatabaseOpenView(hdb, query, &hview);
6630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6631
6632     r = MsiViewExecute(hview, 0);
6633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6634
6635     r = MsiViewFetch(hview, &hrec);
6636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6637
6638     size = MAX_PATH;
6639     r = MsiRecordGetString(hrec, 1, buf, &size);
6640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6641     ok(!lstrcmp(buf, "This is a \"string\" ok"),
6642        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6643
6644     MsiCloseHandle(hrec);
6645
6646     r = MsiViewFetch(hview, &hrec);
6647     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6648
6649     MsiViewClose(hview);
6650     MsiCloseHandle(hview);
6651
6652     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6653
6654     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6656
6657     DeleteFileA("import.idt");
6658
6659     query = "SELECT * FROM `Table`";
6660     r = MsiDatabaseOpenView(hdb, query, &hview);
6661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6662
6663     r = MsiViewExecute(hview, 0);
6664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6665
6666     r = MsiViewFetch(hview, &hrec);
6667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6668
6669     size = MAX_PATH;
6670     r = MsiRecordGetString(hrec, 1, buf, &size);
6671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6672     ok(!lstrcmp(buf, "This is a new 'string' ok"),
6673        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6674
6675     MsiCloseHandle(hrec);
6676
6677     r = MsiViewFetch(hview, &hrec);
6678     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6679
6680     MsiViewClose(hview);
6681     MsiCloseHandle(hview);
6682     MsiCloseHandle(hdb);
6683     DeleteFileA(msifile);
6684 }
6685
6686 static void test_carriagereturn(void)
6687 {
6688     MSIHANDLE hdb, hview, hrec;
6689     const char *query;
6690     char buf[MAX_PATH];
6691     UINT r;
6692     DWORD size;
6693
6694     DeleteFile(msifile);
6695
6696     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6698
6699     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6700     r = run_query(hdb, 0, query);
6701     ok(r == ERROR_BAD_QUERY_SYNTAX,
6702        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6703
6704     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6705     r = run_query(hdb, 0, query);
6706     ok(r == ERROR_BAD_QUERY_SYNTAX,
6707        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6708
6709     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6710     r = run_query(hdb, 0, query);
6711     ok(r == ERROR_BAD_QUERY_SYNTAX,
6712        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6713
6714     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6715     r = run_query(hdb, 0, query);
6716     ok(r == ERROR_BAD_QUERY_SYNTAX,
6717        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6718
6719     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6720     r = run_query(hdb, 0, query);
6721     ok(r == ERROR_BAD_QUERY_SYNTAX,
6722        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6723
6724     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6725     r = run_query(hdb, 0, query);
6726     ok(r == ERROR_BAD_QUERY_SYNTAX,
6727        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6728
6729     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6730     r = run_query(hdb, 0, query);
6731     ok(r == ERROR_BAD_QUERY_SYNTAX,
6732        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6733
6734     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6735     r = run_query(hdb, 0, query);
6736     ok(r == ERROR_BAD_QUERY_SYNTAX,
6737        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6738
6739     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6740     r = run_query(hdb, 0, query);
6741     ok(r == ERROR_BAD_QUERY_SYNTAX,
6742        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6743
6744     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6745     r = run_query(hdb, 0, query);
6746     ok(r == ERROR_BAD_QUERY_SYNTAX,
6747        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6748
6749     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6750     r = run_query(hdb, 0, query);
6751     ok(r == ERROR_BAD_QUERY_SYNTAX,
6752        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6753
6754     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r 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` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `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 TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `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 `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
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` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
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 `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6780     r = run_query(hdb, 0, query);
6781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6782
6783     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6784     r = run_query(hdb, 0, query);
6785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6786
6787     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6788     r = run_query(hdb, 0, query);
6789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6790
6791     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6792     r = run_query(hdb, 0, query);
6793     ok(r == ERROR_BAD_QUERY_SYNTAX,
6794        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6795
6796     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6797     r = run_query(hdb, 0, query);
6798     ok(r == ERROR_BAD_QUERY_SYNTAX,
6799        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6800
6801     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6802     r = run_query(hdb, 0, query);
6803     ok(r == ERROR_BAD_QUERY_SYNTAX,
6804        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6805
6806     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6807     r = run_query(hdb, 0, query);
6808     ok(r == ERROR_BAD_QUERY_SYNTAX,
6809        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6810
6811     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6812     r = run_query(hdb, 0, query);
6813     ok(r == ERROR_BAD_QUERY_SYNTAX,
6814        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6815
6816     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6817     r = run_query(hdb, 0, query);
6818     ok(r == ERROR_BAD_QUERY_SYNTAX,
6819        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6820
6821     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6822     r = run_query(hdb, 0, query);
6823     ok(r == ERROR_BAD_QUERY_SYNTAX,
6824        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6825
6826     query = "SELECT * FROM `_Tables`";
6827     r = MsiDatabaseOpenView(hdb, query, &hview);
6828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6829     r = MsiViewExecute(hview, 0);
6830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6831
6832     r = MsiViewFetch(hview, &hrec);
6833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6834
6835     size = MAX_PATH;
6836     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6838     ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6839
6840     MsiCloseHandle(hrec);
6841
6842     r = MsiViewFetch(hview, &hrec);
6843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6844
6845     size = MAX_PATH;
6846     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6848     ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6849
6850     MsiCloseHandle(hrec);
6851
6852     r = MsiViewFetch(hview, &hrec);
6853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6854
6855     size = MAX_PATH;
6856     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6858     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6859
6860     MsiCloseHandle(hrec);
6861
6862     r = MsiViewFetch(hview, &hrec);
6863     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6864
6865     MsiViewClose(hview);
6866     MsiCloseHandle(hview);
6867
6868     MsiCloseHandle(hdb);
6869     DeleteFileA(msifile);
6870 }
6871
6872 static void test_noquotes(void)
6873 {
6874     MSIHANDLE hdb, hview, hrec;
6875     const char *query;
6876     char buf[MAX_PATH];
6877     UINT r;
6878     DWORD size;
6879
6880     DeleteFile(msifile);
6881
6882     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6884
6885     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6886     r = run_query(hdb, 0, query);
6887     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6888
6889     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6890     r = run_query(hdb, 0, query);
6891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6892
6893     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6894     r = run_query(hdb, 0, query);
6895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6896
6897     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6898     r = run_query(hdb, 0, query);
6899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6900
6901     query = "SELECT * FROM `_Tables`";
6902     r = MsiDatabaseOpenView(hdb, query, &hview);
6903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6904     r = MsiViewExecute(hview, 0);
6905     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
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, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6914
6915     MsiCloseHandle(hrec);
6916
6917     r = MsiViewFetch(hview, &hrec);
6918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6919
6920     size = MAX_PATH;
6921     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6923     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6924
6925     MsiCloseHandle(hrec);
6926
6927     r = MsiViewFetch(hview, &hrec);
6928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6929
6930     size = MAX_PATH;
6931     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6933     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6934
6935     MsiCloseHandle(hrec);
6936
6937     r = MsiViewFetch(hview, &hrec);
6938     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6939
6940     MsiViewClose(hview);
6941     MsiCloseHandle(hview);
6942
6943     query = "SELECT * FROM `_Columns`";
6944     r = MsiDatabaseOpenView(hdb, query, &hview);
6945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6946     r = MsiViewExecute(hview, 0);
6947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6948
6949     r = MsiViewFetch(hview, &hrec);
6950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6951
6952     size = MAX_PATH;
6953     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6955     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6956
6957     r = MsiRecordGetInteger(hrec, 2);
6958     ok(r == 1, "Expected 1, got %d\n", r);
6959
6960     size = MAX_PATH;
6961     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6963     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6964
6965     MsiCloseHandle(hrec);
6966
6967     r = MsiViewFetch(hview, &hrec);
6968     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6969
6970     size = MAX_PATH;
6971     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6973     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6974
6975     r = MsiRecordGetInteger(hrec, 2);
6976     ok(r == 1, "Expected 1, got %d\n", r);
6977
6978     size = MAX_PATH;
6979     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6981     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6982
6983     MsiCloseHandle(hrec);
6984
6985     r = MsiViewFetch(hview, &hrec);
6986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6987
6988     size = MAX_PATH;
6989     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6991     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6992
6993     r = MsiRecordGetInteger(hrec, 2);
6994     ok(r == 1, "Expected 1, got %d\n", r);
6995
6996     size = MAX_PATH;
6997     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6999     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7000
7001     MsiCloseHandle(hrec);
7002
7003     r = MsiViewFetch(hview, &hrec);
7004     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7005
7006     MsiViewClose(hview);
7007     MsiCloseHandle(hview);
7008
7009     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
7010     r = run_query(hdb, 0, query);
7011     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7012
7013     query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
7014     r = run_query(hdb, 0, query);
7015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7016
7017     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
7018     r = run_query(hdb, 0, query);
7019     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7020
7021     query = "SELECT * FROM Table WHERE `A` = 'hi'";
7022     r = run_query(hdb, 0, query);
7023     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7024
7025     query = "SELECT * FROM `Table` WHERE `A` = hi";
7026     r = run_query(hdb, 0, query);
7027     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7028
7029     query = "SELECT * FROM Table";
7030     r = run_query(hdb, 0, query);
7031     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7032
7033     query = "SELECT * FROM Table2";
7034     r = MsiDatabaseOpenView(hdb, query, &hview);
7035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7036     r = MsiViewExecute(hview, 0);
7037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7038
7039     r = MsiViewFetch(hview, &hrec);
7040     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7041
7042     MsiViewClose(hview);
7043     MsiCloseHandle(hview);
7044
7045     query = "SELECT * FROM `Table` WHERE A = 'hi'";
7046     r = MsiDatabaseOpenView(hdb, query, &hview);
7047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7048     r = MsiViewExecute(hview, 0);
7049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7050
7051     r = MsiViewFetch(hview, &hrec);
7052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7053
7054     size = MAX_PATH;
7055     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7057     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7058
7059     MsiCloseHandle(hrec);
7060
7061     r = MsiViewFetch(hview, &hrec);
7062     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7063
7064     MsiViewClose(hview);
7065     MsiCloseHandle(hview);
7066     MsiCloseHandle(hdb);
7067     DeleteFileA(msifile);
7068 }
7069
7070 static void read_file_data(LPCSTR filename, LPSTR buffer)
7071 {
7072     HANDLE file;
7073     DWORD read;
7074
7075     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
7076     ZeroMemory(buffer, MAX_PATH);
7077     ReadFile(file, buffer, MAX_PATH, &read, NULL);
7078     CloseHandle(file);
7079 }
7080
7081 static void test_forcecodepage(void)
7082 {
7083     MSIHANDLE hdb;
7084     const char *query;
7085     char buffer[MAX_PATH];
7086     UINT r;
7087
7088     DeleteFile(msifile);
7089     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
7090
7091     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7093
7094     query = "SELECT * FROM `_ForceCodepage`";
7095     r = run_query(hdb, 0, query);
7096     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7097
7098     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7099     r = run_query(hdb, 0, query);
7100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7101
7102     query = "SELECT * FROM `_ForceCodepage`";
7103     r = run_query(hdb, 0, query);
7104     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7105
7106     r = MsiDatabaseCommit(hdb);
7107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7108
7109     query = "SELECT * FROM `_ForceCodepage`";
7110     r = run_query(hdb, 0, query);
7111     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7112
7113     MsiCloseHandle(hdb);
7114
7115     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb);
7116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7117
7118     query = "SELECT * FROM `_ForceCodepage`";
7119     r = run_query(hdb, 0, query);
7120     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7121
7122     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7124
7125     read_file_data("forcecodepage.idt", buffer);
7126     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7127        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7128
7129     create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7130
7131     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7133
7134     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7136
7137     read_file_data("forcecodepage.idt", buffer);
7138     ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
7139        "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7140
7141     create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
7142
7143     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7144     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_SUCCESS, got %d\n", r);
7145
7146     MsiCloseHandle(hdb);
7147     DeleteFileA(msifile);
7148     DeleteFileA("forcecodepage.idt");
7149 }
7150
7151 static void test_viewmodify_refresh(void)
7152 {
7153     MSIHANDLE hdb, hview, hrec;
7154     const char *query;
7155     char buffer[MAX_PATH];
7156     UINT r;
7157     DWORD size;
7158
7159     DeleteFile(msifile);
7160
7161     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7163
7164     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7165     r = run_query(hdb, 0, query);
7166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7167
7168     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7169     r = run_query(hdb, 0, query);
7170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7171
7172     query = "SELECT * FROM `Table`";
7173     r = MsiDatabaseOpenView(hdb, query, &hview);
7174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7175     r = MsiViewExecute(hview, 0);
7176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7177
7178     r = MsiViewFetch(hview, &hrec);
7179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7180
7181     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7182     r = run_query(hdb, 0, query);
7183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7184
7185     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7187
7188     size = MAX_PATH;
7189     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7191     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7192     ok(size == 2, "Expected 2, got %d\n", size);
7193
7194     r = MsiRecordGetInteger(hrec, 2);
7195     ok(r == 2, "Expected 2, got %d\n", r);
7196
7197     MsiCloseHandle(hrec);
7198     MsiViewClose(hview);
7199     MsiCloseHandle(hview);
7200
7201     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7202     r = run_query(hdb, 0, query);
7203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7204
7205     query = "SELECT * FROM `Table` WHERE `B` = 3";
7206     r = MsiDatabaseOpenView(hdb, query, &hview);
7207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7208     r = MsiViewExecute(hview, 0);
7209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7210
7211     r = MsiViewFetch(hview, &hrec);
7212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7213
7214     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7215     r = run_query(hdb, 0, query);
7216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7217
7218     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7219     r = run_query(hdb, 0, query);
7220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7221
7222     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7224
7225     size = MAX_PATH;
7226     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7228     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7229     ok(size == 5, "Expected 5, got %d\n", size);
7230
7231     r = MsiRecordGetInteger(hrec, 2);
7232     ok(r == 2, "Expected 2, got %d\n", r);
7233
7234     MsiCloseHandle(hrec);
7235     MsiViewClose(hview);
7236     MsiCloseHandle(hview);
7237     MsiCloseHandle(hdb);
7238     DeleteFileA(msifile);
7239 }
7240
7241 static void test_where_viewmodify(void)
7242 {
7243     MSIHANDLE hdb, hview, hrec;
7244     const char *query;
7245     UINT r;
7246
7247     DeleteFile(msifile);
7248
7249     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7251
7252     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7253     r = run_query(hdb, 0, query);
7254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7255
7256     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7257     r = run_query(hdb, 0, query);
7258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7259
7260     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7261     r = run_query(hdb, 0, query);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263
7264     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7265     r = run_query(hdb, 0, query);
7266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7267
7268     /* `B` = 3 doesn't match, but the view shouldn't be executed */
7269     query = "SELECT * FROM `Table` WHERE `B` = 3";
7270     r = MsiDatabaseOpenView(hdb, query, &hview);
7271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7272
7273     hrec = MsiCreateRecord(2);
7274     MsiRecordSetInteger(hrec, 1, 7);
7275     MsiRecordSetInteger(hrec, 2, 8);
7276
7277     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7279
7280     MsiCloseHandle(hrec);
7281     MsiViewClose(hview);
7282     MsiCloseHandle(hview);
7283
7284     query = "SELECT * FROM `Table` WHERE `A` = 7";
7285     r = MsiDatabaseOpenView(hdb, query, &hview);
7286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287     r = MsiViewExecute(hview, 0);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289
7290     r = MsiViewFetch(hview, &hrec);
7291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7292
7293     r = MsiRecordGetInteger(hrec, 1);
7294     ok(r == 7, "Expected 7, got %d\n", r);
7295
7296     r = MsiRecordGetInteger(hrec, 2);
7297     ok(r == 8, "Expected 8, got %d\n", r);
7298
7299     MsiRecordSetInteger(hrec, 2, 9);
7300
7301     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7303
7304     MsiCloseHandle(hrec);
7305     MsiViewClose(hview);
7306     MsiCloseHandle(hview);
7307
7308     query = "SELECT * FROM `Table` WHERE `A` = 7";
7309     r = MsiDatabaseOpenView(hdb, query, &hview);
7310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7311     r = MsiViewExecute(hview, 0);
7312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7313
7314     r = MsiViewFetch(hview, &hrec);
7315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7316
7317     r = MsiRecordGetInteger(hrec, 1);
7318     ok(r == 7, "Expected 7, got %d\n", r);
7319
7320     r = MsiRecordGetInteger(hrec, 2);
7321     ok(r == 9, "Expected 9, got %d\n", r);
7322
7323     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7324     r = run_query(hdb, 0, query);
7325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7326
7327     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7329
7330     r = MsiRecordGetInteger(hrec, 1);
7331     ok(r == 7, "Expected 7, got %d\n", r);
7332
7333     r = MsiRecordGetInteger(hrec, 2);
7334     ok(r == 10, "Expected 10, got %d\n", r);
7335
7336     MsiCloseHandle(hrec);
7337     MsiViewClose(hview);
7338     MsiCloseHandle(hview);
7339     MsiCloseHandle(hdb);
7340 }
7341
7342 static BOOL create_storage(LPCSTR name)
7343 {
7344     WCHAR nameW[MAX_PATH];
7345     IStorage *stg;
7346     IStream *stm;
7347     HRESULT hr;
7348     DWORD count;
7349     BOOL res = FALSE;
7350
7351     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7352     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7353                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7354     if (FAILED(hr))
7355         return FALSE;
7356
7357     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7358                                0, 0, &stm);
7359     if (FAILED(hr))
7360         goto done;
7361
7362     hr = IStream_Write(stm, "stgdata", 8, &count);
7363     if (SUCCEEDED(hr))
7364         res = TRUE;
7365
7366 done:
7367     IStream_Release(stm);
7368     IStorage_Release(stg);
7369
7370     return res;
7371 }
7372
7373 static void test_storages_table(void)
7374 {
7375     MSIHANDLE hdb, hview, hrec;
7376     IStorage *stg, *inner;
7377     IStream *stm;
7378     char file[MAX_PATH];
7379     char buf[MAX_PATH];
7380     WCHAR name[MAX_PATH];
7381     LPCSTR query;
7382     HRESULT hr;
7383     DWORD size;
7384     UINT r;
7385
7386     hdb = create_db();
7387     ok(hdb, "failed to create db\n");
7388
7389     r = MsiDatabaseCommit(hdb);
7390     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7391
7392     MsiCloseHandle(hdb);
7393
7394     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
7395     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7396
7397     /* check the column types */
7398     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7399     ok(hrec, "failed to get column info hrecord\n");
7400     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7401     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7402
7403     MsiCloseHandle(hrec);
7404
7405     /* now try the names */
7406     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7407     ok(hrec, "failed to get column info hrecord\n");
7408     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7409     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7410
7411     MsiCloseHandle(hrec);
7412
7413     create_storage("storage.bin");
7414
7415     hrec = MsiCreateRecord(2);
7416     MsiRecordSetString(hrec, 1, "stgname");
7417
7418     r = MsiRecordSetStream(hrec, 2, "storage.bin");
7419     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7420
7421     DeleteFileA("storage.bin");
7422
7423     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7424     r = MsiDatabaseOpenView(hdb, query, &hview);
7425     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7426
7427     r = MsiViewExecute(hview, hrec);
7428     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7429
7430     MsiCloseHandle(hrec);
7431     MsiViewClose(hview);
7432     MsiCloseHandle(hview);
7433
7434     query = "SELECT `Name`, `Data` FROM `_Storages`";
7435     r = MsiDatabaseOpenView(hdb, query, &hview);
7436     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7437
7438     r = MsiViewExecute(hview, 0);
7439     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7440
7441     r = MsiViewFetch(hview, &hrec);
7442     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7443
7444     size = MAX_PATH;
7445     r = MsiRecordGetString(hrec, 1, file, &size);
7446     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7447     ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7448
7449     size = MAX_PATH;
7450     lstrcpyA(buf, "apple");
7451     r = MsiRecordReadStream(hrec, 2, buf, &size);
7452     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7453     ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7454     ok(size == 0, "Expected 0, got %d\n", size);
7455
7456     MsiCloseHandle(hrec);
7457
7458     r = MsiViewFetch(hview, &hrec);
7459     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7460
7461     MsiViewClose(hview);
7462     MsiCloseHandle(hview);
7463
7464     MsiDatabaseCommit(hdb);
7465     MsiCloseHandle(hdb);
7466
7467     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7468     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7469                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7470     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7471     ok(stg != NULL, "Expected non-NULL storage\n");
7472
7473     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7474     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7475                               NULL, 0, &inner);
7476     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7477     ok(inner != NULL, "Expected non-NULL storage\n");
7478
7479     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7480     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7481     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7482     ok(stm != NULL, "Expected non-NULL stream\n");
7483
7484     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7485     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7486     ok(size == 8, "Expected 8, got %d\n", size);
7487     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7488
7489     IStream_Release(stm);
7490     IStorage_Release(inner);
7491
7492     IStorage_Release(stg);
7493     DeleteFileA(msifile);
7494 }
7495
7496 static void test_dbtopackage(void)
7497 {
7498     MSIHANDLE hdb, hpkg;
7499     CHAR package[12], buf[MAX_PATH];
7500     DWORD size;
7501     UINT r;
7502
7503     /* create an empty database, transact mode */
7504     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7505     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7506
7507     set_summary_info(hdb);
7508
7509     r = create_directory_table(hdb);
7510     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7511
7512     r = create_custom_action_table(hdb);
7513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7514
7515     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7517
7518     sprintf(package, "#%u", hdb);
7519     r = MsiOpenPackage(package, &hpkg);
7520     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7521     {
7522         skip("Not enough rights to perform tests\n");
7523         goto error;
7524     }
7525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7526
7527     /* property is not set yet */
7528     size = MAX_PATH;
7529     lstrcpyA(buf, "kiwi");
7530     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7532     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7533     ok(size == 0, "Expected 0, got %d\n", size);
7534
7535     /* run the custom action to set the property */
7536     r = MsiDoAction(hpkg, "SetProp");
7537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7538
7539     /* property is now set */
7540     size = MAX_PATH;
7541     lstrcpyA(buf, "kiwi");
7542     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7544     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7545     ok(size == 5, "Expected 5, got %d\n", size);
7546
7547     MsiCloseHandle(hpkg);
7548
7549     /* reset the package */
7550     r = MsiOpenPackage(package, &hpkg);
7551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7552
7553     /* property is not set anymore */
7554     size = MAX_PATH;
7555     lstrcpyA(buf, "kiwi");
7556     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7558     todo_wine
7559     {
7560         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7561         ok(size == 0, "Expected 0, got %d\n", size);
7562     }
7563
7564     MsiCloseHandle(hdb);
7565     MsiCloseHandle(hpkg);
7566
7567     /* create an empty database, direct mode */
7568     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
7569     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7570
7571     set_summary_info(hdb);
7572
7573     r = create_directory_table(hdb);
7574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7575
7576     r = create_custom_action_table(hdb);
7577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7578
7579     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7581
7582     sprintf(package, "#%u", hdb);
7583     r = MsiOpenPackage(package, &hpkg);
7584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7585
7586     /* property is not set yet */
7587     size = MAX_PATH;
7588     lstrcpyA(buf, "kiwi");
7589     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7591     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7592     ok(size == 0, "Expected 0, got %d\n", size);
7593
7594     /* run the custom action to set the property */
7595     r = MsiDoAction(hpkg, "SetProp");
7596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7597
7598     /* property is now set */
7599     size = MAX_PATH;
7600     lstrcpyA(buf, "kiwi");
7601     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7603     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7604     ok(size == 5, "Expected 5, got %d\n", size);
7605
7606     MsiCloseHandle(hpkg);
7607
7608     /* reset the package */
7609     r = MsiOpenPackage(package, &hpkg);
7610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7611
7612     /* property is not set anymore */
7613     size = MAX_PATH;
7614     lstrcpyA(buf, "kiwi");
7615     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7617     todo_wine
7618     {
7619         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7620         ok(size == 0, "Expected 0, got %d\n", size);
7621     }
7622
7623     MsiCloseHandle(hpkg);
7624
7625 error:
7626     MsiCloseHandle(hdb);
7627     DeleteFileA(msifile);
7628 }
7629
7630 static void test_droptable(void)
7631 {
7632     MSIHANDLE hdb, hview, hrec;
7633     CHAR buf[MAX_PATH];
7634     LPCSTR query;
7635     DWORD size;
7636     UINT r;
7637
7638     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7640
7641     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7642     r = run_query(hdb, 0, query);
7643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7644
7645     query = "SELECT * FROM `One`";
7646     r = do_query(hdb, query, &hrec);
7647     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7648
7649     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7650     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7652     r = MsiViewExecute(hview, 0);
7653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7654
7655     r = MsiViewFetch(hview, &hrec);
7656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7657
7658     size = MAX_PATH;
7659     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7661     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7662
7663     MsiCloseHandle(hrec);
7664     MsiViewClose(hview);
7665     MsiCloseHandle(hview);
7666
7667     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7668     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7670     r = MsiViewExecute(hview, 0);
7671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7672
7673     r = MsiViewFetch(hview, &hrec);
7674     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7675
7676     size = MAX_PATH;
7677     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7679     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7680
7681     r = MsiRecordGetInteger(hrec, 2);
7682     ok(r == 1, "Expected 1, got %d\n", r);
7683
7684     size = MAX_PATH;
7685     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7687     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7688
7689     MsiCloseHandle(hrec);
7690
7691     r = MsiViewFetch(hview, &hrec);
7692     ok(r == ERROR_NO_MORE_ITEMS,
7693        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7694
7695     MsiViewClose(hview);
7696     MsiCloseHandle(hview);
7697
7698     query = "DROP `One`";
7699     r = run_query(hdb, 0, query);
7700     ok(r == ERROR_BAD_QUERY_SYNTAX,
7701        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7702
7703     query = "DROP TABLE";
7704     r = run_query(hdb, 0, query);
7705     ok(r == ERROR_BAD_QUERY_SYNTAX,
7706        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7707
7708     query = "DROP TABLE `One`";
7709     hview = 0;
7710     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7712     r = MsiViewExecute(hview, 0);
7713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7714
7715     r = MsiViewFetch(hview, &hrec);
7716     ok(r == ERROR_FUNCTION_FAILED,
7717        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7718
7719     MsiViewClose(hview);
7720     MsiCloseHandle(hview);
7721
7722     query = "SELECT * FROM `IDontExist`";
7723     r = do_query(hdb, query, &hrec);
7724     ok(r == ERROR_BAD_QUERY_SYNTAX,
7725        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7726
7727     query = "SELECT * FROM `One`";
7728     r = do_query(hdb, query, &hrec);
7729     ok(r == ERROR_BAD_QUERY_SYNTAX,
7730        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7731
7732     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7733     r = run_query(hdb, 0, query);
7734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7735
7736     query = "DROP TABLE One";
7737     r = run_query(hdb, 0, query);
7738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7739
7740     query = "SELECT * FROM `One`";
7741     r = do_query(hdb, query, &hrec);
7742     ok(r == ERROR_BAD_QUERY_SYNTAX,
7743        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7744
7745     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7746     r = do_query(hdb, query, &hrec);
7747     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7748
7749     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7750     r = do_query(hdb, query, &hrec);
7751     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7752
7753     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7754     r = run_query(hdb, 0, query);
7755     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7756
7757     query = "SELECT * FROM `One`";
7758     r = do_query(hdb, query, &hrec);
7759     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7760
7761     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7762     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7764     r = MsiViewExecute(hview, 0);
7765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7766
7767     r = MsiViewFetch(hview, &hrec);
7768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7769
7770     size = MAX_PATH;
7771     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7772     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7773     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7774
7775     MsiCloseHandle(hrec);
7776     MsiViewClose(hview);
7777     MsiCloseHandle(hview);
7778
7779     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7780     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7782     r = MsiViewExecute(hview, 0);
7783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7784
7785     r = MsiViewFetch(hview, &hrec);
7786     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7787
7788     size = MAX_PATH;
7789     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7791     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7792
7793     r = MsiRecordGetInteger(hrec, 2);
7794     ok(r == 1, "Expected 1, got %d\n", r);
7795
7796     size = MAX_PATH;
7797     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7799     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7800
7801     MsiCloseHandle(hrec);
7802
7803     r = MsiViewFetch(hview, &hrec);
7804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7805
7806     size = MAX_PATH;
7807     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7809     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7810
7811     r = MsiRecordGetInteger(hrec, 2);
7812     ok(r == 2, "Expected 2, got %d\n", r);
7813
7814     size = MAX_PATH;
7815     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7817     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7818
7819     MsiCloseHandle(hrec);
7820
7821     r = MsiViewFetch(hview, &hrec);
7822     ok(r == ERROR_NO_MORE_ITEMS,
7823        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7824
7825     MsiViewClose(hview);
7826     MsiCloseHandle(hview);
7827
7828     query = "DROP TABLE One";
7829     r = run_query(hdb, 0, query);
7830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7831
7832     query = "SELECT * FROM `One`";
7833     r = do_query(hdb, query, &hrec);
7834     ok(r == ERROR_BAD_QUERY_SYNTAX,
7835        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7836
7837     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7838     r = do_query(hdb, query, &hrec);
7839     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7840
7841     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7842     r = do_query(hdb, query, &hrec);
7843     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7844
7845     MsiCloseHandle(hdb);
7846     DeleteFileA(msifile);
7847 }
7848
7849 static void test_dbmerge(void)
7850 {
7851     MSIHANDLE hdb, href, hview, hrec;
7852     CHAR buf[MAX_PATH];
7853     LPCSTR query;
7854     DWORD size;
7855     UINT r;
7856
7857     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7858     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7859
7860     r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
7861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7862
7863     /* hDatabase is invalid */
7864     r = MsiDatabaseMergeA(0, href, "MergeErrors");
7865     ok(r == ERROR_INVALID_HANDLE,
7866        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7867
7868     /* hDatabaseMerge is invalid */
7869     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7870     ok(r == ERROR_INVALID_HANDLE,
7871        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7872
7873     /* szTableName is NULL */
7874     r = MsiDatabaseMergeA(hdb, href, NULL);
7875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7876
7877     /* szTableName is empty */
7878     r = MsiDatabaseMergeA(hdb, href, "");
7879     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7880
7881     /* both DBs empty, szTableName is valid */
7882     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7884
7885     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7886     r = run_query(hdb, 0, query);
7887     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7888
7889     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7890     r = run_query(href, 0, query);
7891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7892
7893     /* column types don't match */
7894     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7895     ok(r == ERROR_DATATYPE_MISMATCH,
7896        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7897
7898     /* nothing in MergeErrors */
7899     query = "SELECT * FROM `MergeErrors`";
7900     r = do_query(hdb, query, &hrec);
7901     ok(r == ERROR_BAD_QUERY_SYNTAX,
7902        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7903
7904     query = "DROP TABLE `One`";
7905     r = run_query(hdb, 0, query);
7906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7907
7908     query = "DROP TABLE `One`";
7909     r = run_query(href, 0, query);
7910     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7911
7912     query = "CREATE TABLE `One` ( "
7913         "`A` CHAR(72), "
7914         "`B` CHAR(56), "
7915         "`C` CHAR(64) LOCALIZABLE, "
7916         "`D` LONGCHAR, "
7917         "`E` CHAR(72) NOT NULL, "
7918         "`F` CHAR(56) NOT NULL, "
7919         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7920         "`H` LONGCHAR NOT NULL "
7921         "PRIMARY KEY `A` )";
7922     r = run_query(hdb, 0, query);
7923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7924
7925     query = "CREATE TABLE `One` ( "
7926         "`A` CHAR(64), "
7927         "`B` CHAR(64), "
7928         "`C` CHAR(64), "
7929         "`D` CHAR(64), "
7930         "`E` CHAR(64) NOT NULL, "
7931         "`F` CHAR(64) NOT NULL, "
7932         "`G` CHAR(64) NOT NULL, "
7933         "`H` CHAR(64) NOT NULL "
7934         "PRIMARY KEY `A` )";
7935     r = run_query(href, 0, query);
7936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7937
7938     /* column sting types don't match exactly */
7939     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7940     ok(r == ERROR_SUCCESS,
7941        "Expected ERROR_SUCCESS, got %d\n", r);
7942
7943     /* nothing in MergeErrors */
7944     query = "SELECT * FROM `MergeErrors`";
7945     r = do_query(hdb, query, &hrec);
7946     ok(r == ERROR_BAD_QUERY_SYNTAX,
7947        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7948
7949     query = "DROP TABLE `One`";
7950     r = run_query(hdb, 0, query);
7951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7952
7953     query = "DROP TABLE `One`";
7954     r = run_query(href, 0, query);
7955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7956
7957     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7958     r = run_query(hdb, 0, query);
7959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7960
7961     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
7962     r = run_query(href, 0, query);
7963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7964
7965     /* column names don't match */
7966     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7967     ok(r == ERROR_DATATYPE_MISMATCH,
7968        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7969
7970     /* nothing in MergeErrors */
7971     query = "SELECT * FROM `MergeErrors`";
7972     r = do_query(hdb, query, &hrec);
7973     ok(r == ERROR_BAD_QUERY_SYNTAX,
7974        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7975
7976     query = "DROP TABLE `One`";
7977     r = run_query(hdb, 0, query);
7978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7979
7980     query = "DROP TABLE `One`";
7981     r = run_query(href, 0, query);
7982     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7983
7984     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7985     r = run_query(hdb, 0, query);
7986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7987
7988     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
7989     r = run_query(href, 0, query);
7990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7991
7992     /* primary keys don't match */
7993     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7994     ok(r == ERROR_DATATYPE_MISMATCH,
7995        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7996
7997     /* nothing in MergeErrors */
7998     query = "SELECT * FROM `MergeErrors`";
7999     r = do_query(hdb, query, &hrec);
8000     ok(r == ERROR_BAD_QUERY_SYNTAX,
8001        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8002
8003     query = "DROP TABLE `One`";
8004     r = run_query(hdb, 0, query);
8005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8006
8007     query = "DROP TABLE `One`";
8008     r = run_query(href, 0, query);
8009     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8010
8011     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8012     r = run_query(hdb, 0, query);
8013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8014
8015     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
8016     r = run_query(href, 0, query);
8017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8018
8019     /* number of primary keys doesn't match */
8020     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8021     ok(r == ERROR_DATATYPE_MISMATCH,
8022        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8023
8024     /* nothing in MergeErrors */
8025     query = "SELECT * FROM `MergeErrors`";
8026     r = do_query(hdb, query, &hrec);
8027     ok(r == ERROR_BAD_QUERY_SYNTAX,
8028        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8029
8030     query = "DROP TABLE `One`";
8031     r = run_query(hdb, 0, query);
8032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8033
8034     query = "DROP TABLE `One`";
8035     r = run_query(href, 0, query);
8036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8037
8038     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8039     r = run_query(hdb, 0, query);
8040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8041
8042     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8043     r = run_query(href, 0, query);
8044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8045
8046     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8047     r = run_query(href, 0, query);
8048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8049
8050     /* number of columns doesn't match */
8051     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8053
8054     query = "SELECT * FROM `One`";
8055     r = do_query(hdb, query, &hrec);
8056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8057
8058     r = MsiRecordGetInteger(hrec, 1);
8059     ok(r == 1, "Expected 1, got %d\n", r);
8060
8061     r = MsiRecordGetInteger(hrec, 2);
8062     ok(r == 2, "Expected 2, got %d\n", r);
8063
8064     r = MsiRecordGetInteger(hrec, 3);
8065     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8066
8067     MsiCloseHandle(hrec);
8068
8069     /* nothing in MergeErrors */
8070     query = "SELECT * FROM `MergeErrors`";
8071     r = do_query(hdb, query, &hrec);
8072     ok(r == ERROR_BAD_QUERY_SYNTAX,
8073        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8074
8075     query = "DROP TABLE `One`";
8076     r = run_query(hdb, 0, query);
8077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8078
8079     query = "DROP TABLE `One`";
8080     r = run_query(href, 0, query);
8081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8082
8083     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8084     r = run_query(hdb, 0, query);
8085     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8086
8087     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8088     r = run_query(href, 0, query);
8089     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8090
8091     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8092     r = run_query(href, 0, query);
8093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8094
8095     /* number of columns doesn't match */
8096     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8098
8099     query = "SELECT * FROM `One`";
8100     r = do_query(hdb, query, &hrec);
8101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8102
8103     r = MsiRecordGetInteger(hrec, 1);
8104     ok(r == 1, "Expected 1, got %d\n", r);
8105
8106     r = MsiRecordGetInteger(hrec, 2);
8107     ok(r == 2, "Expected 2, got %d\n", r);
8108
8109     r = MsiRecordGetInteger(hrec, 3);
8110     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8111
8112     MsiCloseHandle(hrec);
8113
8114     /* nothing in MergeErrors */
8115     query = "SELECT * FROM `MergeErrors`";
8116     r = do_query(hdb, query, &hrec);
8117     ok(r == ERROR_BAD_QUERY_SYNTAX,
8118        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8119
8120     query = "DROP TABLE `One`";
8121     r = run_query(hdb, 0, query);
8122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8123
8124     query = "DROP TABLE `One`";
8125     r = run_query(href, 0, query);
8126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8127
8128     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8129     r = run_query(hdb, 0, query);
8130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8131
8132     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
8133     r = run_query(hdb, 0, query);
8134     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8135
8136     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8137     r = run_query(hdb, 0, query);
8138     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8139
8140     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8141     r = run_query(href, 0, query);
8142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8143
8144     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8145     r = run_query(href, 0, query);
8146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8147
8148     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
8149     r = run_query(href, 0, query);
8150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8151
8152     /* primary keys match, rows do not */
8153     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8154     ok(r == ERROR_FUNCTION_FAILED,
8155        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8156
8157     /* nothing in MergeErrors */
8158     query = "SELECT * FROM `MergeErrors`";
8159     r = do_query(hdb, query, &hrec);
8160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8161
8162     size = MAX_PATH;
8163     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8165     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8166
8167     r = MsiRecordGetInteger(hrec, 2);
8168     ok(r == 2, "Expected 2, got %d\n", r);
8169
8170     MsiCloseHandle(hrec);
8171
8172     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8174
8175     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8177
8178     size = MAX_PATH;
8179     r = MsiRecordGetString(hrec, 1, buf, &size);
8180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8181     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8182
8183     size = MAX_PATH;
8184     r = MsiRecordGetString(hrec, 2, buf, &size);
8185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8186     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8187        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8188
8189     MsiCloseHandle(hrec);
8190
8191     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8193
8194     size = MAX_PATH;
8195     r = MsiRecordGetString(hrec, 1, buf, &size);
8196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8197     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8198
8199     size = MAX_PATH;
8200     r = MsiRecordGetString(hrec, 2, buf, &size);
8201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8202     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8203
8204     MsiCloseHandle(hrec);
8205     MsiViewClose(hview);
8206     MsiCloseHandle(hview);
8207
8208     query = "DROP TABLE `MergeErrors`";
8209     r = run_query(hdb, 0, query);
8210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8211
8212     query = "DROP TABLE `One`";
8213     r = run_query(hdb, 0, query);
8214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8215
8216     query = "DROP TABLE `One`";
8217     r = run_query(href, 0, query);
8218     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8219
8220     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8221     r = run_query(href, 0, query);
8222     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8223
8224     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8225     r = run_query(href, 0, query);
8226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8227
8228     /* table from merged database is not in target database */
8229     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8231
8232     query = "SELECT * FROM `One`";
8233     r = do_query(hdb, query, &hrec);
8234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8235
8236     r = MsiRecordGetInteger(hrec, 1);
8237     ok(r == 1, "Expected 1, got %d\n", r);
8238
8239     size = MAX_PATH;
8240     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8242     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8243
8244     MsiCloseHandle(hrec);
8245
8246     /* nothing in MergeErrors */
8247     query = "SELECT * FROM `MergeErrors`";
8248     r = do_query(hdb, query, &hrec);
8249     ok(r == ERROR_BAD_QUERY_SYNTAX,
8250        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8251
8252     query = "DROP TABLE `One`";
8253     r = run_query(hdb, 0, query);
8254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8255
8256     query = "DROP TABLE `One`";
8257     r = run_query(href, 0, query);
8258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8259
8260     query = "CREATE TABLE `One` ( "
8261             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8262     r = run_query(hdb, 0, query);
8263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8264
8265     query = "CREATE TABLE `One` ( "
8266             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8267     r = run_query(href, 0, query);
8268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8269
8270     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8271     r = run_query(href, 0, query);
8272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8273
8274     /* primary key is string */
8275     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8276     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8277
8278     query = "SELECT * FROM `One`";
8279     r = do_query(hdb, query, &hrec);
8280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8281
8282     size = MAX_PATH;
8283     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8285     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8286
8287     r = MsiRecordGetInteger(hrec, 2);
8288     ok(r == 1, "Expected 1, got %d\n", r);
8289
8290     MsiCloseHandle(hrec);
8291
8292     /* nothing in MergeErrors */
8293     query = "SELECT * FROM `MergeErrors`";
8294     r = do_query(hdb, query, &hrec);
8295     ok(r == ERROR_BAD_QUERY_SYNTAX,
8296        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8297
8298     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8299
8300     GetCurrentDirectoryA(MAX_PATH, buf);
8301     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8303
8304     query = "DROP TABLE `One`";
8305     r = run_query(hdb, 0, query);
8306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8307
8308     query = "DROP TABLE `One`";
8309     r = run_query(href, 0, query);
8310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8311
8312     query = "CREATE TABLE `One` ( "
8313             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8314     r = run_query(hdb, 0, query);
8315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8316
8317     query = "CREATE TABLE `One` ( "
8318             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8319     r = run_query(href, 0, query);
8320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8321
8322     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8323     r = run_query(href, 0, query);
8324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8325
8326     /* code page does not match */
8327     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8329
8330     query = "SELECT * FROM `One`";
8331     r = do_query(hdb, query, &hrec);
8332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8333
8334     r = MsiRecordGetInteger(hrec, 1);
8335     ok(r == 1, "Expected 1, got %d\n", r);
8336
8337     size = MAX_PATH;
8338     r = MsiRecordGetStringA(hrec, 2, 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     MsiCloseHandle(hrec);
8343
8344     /* nothing in MergeErrors */
8345     query = "SELECT * FROM `MergeErrors`";
8346     r = do_query(hdb, query, &hrec);
8347     ok(r == ERROR_BAD_QUERY_SYNTAX,
8348        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8349
8350     query = "DROP TABLE `One`";
8351     r = run_query(hdb, 0, query);
8352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8353
8354     query = "DROP TABLE `One`";
8355     r = run_query(href, 0, query);
8356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8357
8358     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8359     r = run_query(hdb, 0, query);
8360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8361
8362     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8363     r = run_query(href, 0, query);
8364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8365
8366     create_file("binary.dat");
8367     hrec = MsiCreateRecord(1);
8368     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8369
8370     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8371     r = run_query(href, hrec, query);
8372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8373
8374     MsiCloseHandle(hrec);
8375
8376     /* binary data to merge */
8377     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8379
8380     query = "SELECT * FROM `One`";
8381     r = do_query(hdb, query, &hrec);
8382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8383
8384     r = MsiRecordGetInteger(hrec, 1);
8385     ok(r == 1, "Expected 1, got %d\n", r);
8386
8387     size = MAX_PATH;
8388     ZeroMemory(buf, MAX_PATH);
8389     r = MsiRecordReadStream(hrec, 2, buf, &size);
8390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8391     ok(!lstrcmpA(buf, "binary.dat\n"),
8392        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8393
8394     MsiCloseHandle(hrec);
8395
8396     /* nothing in MergeErrors */
8397     query = "SELECT * FROM `MergeErrors`";
8398     r = do_query(hdb, query, &hrec);
8399     ok(r == ERROR_BAD_QUERY_SYNTAX,
8400        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8401
8402     query = "DROP TABLE `One`";
8403     r = run_query(hdb, 0, query);
8404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8405
8406     query = "DROP TABLE `One`";
8407     r = run_query(href, 0, query);
8408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8409
8410     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8411     r = run_query(hdb, 0, query);
8412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8413     r = run_query(href, 0, query);
8414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8415
8416     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8417     r = run_query(href, 0, query);
8418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8419
8420     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8421     r = run_query(href, 0, query);
8422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8423
8424     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8426
8427     query = "SELECT * FROM `One`";
8428     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8430     r = MsiViewExecute(hview, 0);
8431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8432
8433     r = MsiViewFetch(hview, &hrec);
8434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8435
8436     r = MsiRecordGetInteger(hrec, 1);
8437     ok(r == 1, "Expected 1, got %d\n", r);
8438
8439     size = MAX_PATH;
8440     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8442     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8443
8444     MsiCloseHandle(hrec);
8445
8446     r = MsiViewFetch(hview, &hrec);
8447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8448
8449     r = MsiRecordGetInteger(hrec, 1);
8450     ok(r == 2, "Expected 2, got %d\n", r);
8451
8452     size = MAX_PATH;
8453     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8455     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8456
8457     MsiCloseHandle(hrec);
8458
8459     r = MsiViewFetch(hview, &hrec);
8460     ok(r == ERROR_NO_MORE_ITEMS,
8461        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8462
8463     MsiViewClose(hview);
8464     MsiCloseHandle(hview);
8465
8466     MsiCloseHandle(hdb);
8467     MsiCloseHandle(href);
8468     DeleteFileA(msifile);
8469     DeleteFileA("refdb.msi");
8470     DeleteFileA("codepage.idt");
8471     DeleteFileA("binary.dat");
8472 }
8473
8474 static void test_select_with_tablenames(void)
8475 {
8476     MSIHANDLE hdb, view, rec;
8477     LPCSTR query;
8478     UINT r;
8479     int i;
8480
8481     int vals[4][2] = {
8482         {1,12},
8483         {4,12},
8484         {1,15},
8485         {4,15}};
8486
8487     hdb = create_db();
8488     ok(hdb, "failed to create db\n");
8489
8490     /* Build a pair of tables with the same column names, but unique data */
8491     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8492     r = run_query(hdb, 0, query);
8493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8494
8495     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8496     r = run_query(hdb, 0, query);
8497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8498
8499     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8500     r = run_query(hdb, 0, query);
8501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8502
8503     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8504     r = run_query(hdb, 0, query);
8505     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8506
8507     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8508     r = run_query(hdb, 0, query);
8509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8510
8511     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8512     r = run_query(hdb, 0, query);
8513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8514
8515
8516     /* Test that selection based on prefixing the column with the table
8517      * actually selects the right data */
8518
8519     query = "SELECT T1.A, T2.B FROM T1,T2";
8520     r = MsiDatabaseOpenView(hdb, query, &view);
8521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8522     r = MsiViewExecute(view, 0);
8523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8524
8525     for (i = 0; i < 4; i++)
8526     {
8527         r = MsiViewFetch(view, &rec);
8528         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8529
8530         r = MsiRecordGetInteger(rec, 1);
8531         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8532
8533         r = MsiRecordGetInteger(rec, 2);
8534         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8535
8536         MsiCloseHandle(rec);
8537     }
8538
8539     r = MsiViewFetch(view, &rec);
8540     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8541
8542     MsiViewClose(view);
8543     MsiCloseHandle(view);
8544     MsiCloseHandle(hdb);
8545     DeleteFileA(msifile);
8546 }
8547
8548 static const UINT ordervals[6][3] =
8549 {
8550     { MSI_NULL_INTEGER, 12, 13 },
8551     { 1, 2, 3 },
8552     { 6, 4, 5 },
8553     { 8, 9, 7 },
8554     { 10, 11, MSI_NULL_INTEGER },
8555     { 14, MSI_NULL_INTEGER, 15 }
8556 };
8557
8558 static void test_insertorder(void)
8559 {
8560     MSIHANDLE hdb, view, rec;
8561     LPCSTR query;
8562     UINT r;
8563     int i;
8564
8565     hdb = create_db();
8566     ok(hdb, "failed to create db\n");
8567
8568     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8569     r = run_query(hdb, 0, query);
8570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8571
8572     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8573     r = run_query(hdb, 0, query);
8574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8575
8576     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8577     r = run_query(hdb, 0, query);
8578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8579
8580     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8581     r = run_query(hdb, 0, query);
8582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8583
8584     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8585     r = run_query(hdb, 0, query);
8586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8587
8588     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8589     r = run_query(hdb, 0, query);
8590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8591
8592     /* fails because the primary key already
8593      * has an MSI_NULL_INTEGER value set above
8594      */
8595     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8596     r = run_query(hdb, 0, query);
8597     ok(r == ERROR_FUNCTION_FAILED,
8598        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8599
8600     /* replicate the error where primary key is set twice */
8601     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8602     r = run_query(hdb, 0, query);
8603     ok(r == ERROR_FUNCTION_FAILED,
8604        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8605
8606     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8607     r = run_query(hdb, 0, query);
8608     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8609
8610     query = "INSERT INTO `T` VALUES ( 16 )";
8611     r = run_query(hdb, 0, query);
8612     ok(r == ERROR_BAD_QUERY_SYNTAX,
8613        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8614
8615     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8616     r = run_query(hdb, 0, query);
8617     ok(r == ERROR_BAD_QUERY_SYNTAX,
8618        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8619
8620     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8621     r = run_query(hdb, 0, query);
8622     ok(r == ERROR_BAD_QUERY_SYNTAX,
8623        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8624
8625     query = "SELECT * FROM `T`";
8626     r = MsiDatabaseOpenView(hdb, query, &view);
8627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8628     r = MsiViewExecute(view, 0);
8629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8630
8631     for (i = 0; i < 6; i++)
8632     {
8633         r = MsiViewFetch(view, &rec);
8634         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8635
8636         r = MsiRecordGetInteger(rec, 1);
8637         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8638
8639         r = MsiRecordGetInteger(rec, 2);
8640         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8641
8642         r = MsiRecordGetInteger(rec, 3);
8643         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8644
8645         MsiCloseHandle(rec);
8646     }
8647
8648     r = MsiViewFetch(view, &rec);
8649     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8650
8651     MsiViewClose(view);
8652     MsiCloseHandle(view);
8653
8654     query = "DELETE FROM `T` WHERE `A` IS NULL";
8655     r = run_query(hdb, 0, query);
8656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8657
8658     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8659     r = run_query(hdb, 0, query);
8660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8661
8662     query = "SELECT * FROM `T`";
8663     r = MsiDatabaseOpenView(hdb, query, &view);
8664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8665     r = MsiViewExecute(view, 0);
8666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8667
8668     for (i = 0; i < 6; i++)
8669     {
8670         r = MsiViewFetch(view, &rec);
8671         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8672
8673         r = MsiRecordGetInteger(rec, 1);
8674         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8675
8676         r = MsiRecordGetInteger(rec, 2);
8677         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8678
8679         r = MsiRecordGetInteger(rec, 3);
8680         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8681
8682         MsiCloseHandle(rec);
8683     }
8684
8685     r = MsiViewFetch(view, &rec);
8686     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8687
8688     MsiViewClose(view);
8689     MsiCloseHandle(view);
8690     MsiCloseHandle(hdb);
8691     DeleteFileA(msifile);
8692 }
8693
8694 static void test_columnorder(void)
8695 {
8696     MSIHANDLE hdb, view, rec;
8697     char buf[MAX_PATH];
8698     LPCSTR query;
8699     DWORD sz;
8700     UINT r;
8701
8702     hdb = create_db();
8703     ok(hdb, "failed to create db\n");
8704
8705     /* Each column is a slot:
8706      * ---------------------
8707      * | B | C | A | E | D |
8708      * ---------------------
8709      *
8710      * When a column is selected as a primary key,
8711      * the column occupying the nth primary key slot is swapped
8712      * with the current position of the primary key in question:
8713      *
8714      * set primary key `D`
8715      * ---------------------    ---------------------
8716      * | B | C | A | E | D | -> | D | C | A | E | B |
8717      * ---------------------    ---------------------
8718      *
8719      * set primary key `E`
8720      * ---------------------    ---------------------
8721      * | D | C | A | E | B | -> | D | E | A | C | B |
8722      * ---------------------    ---------------------
8723      */
8724
8725     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8726             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8727             "PRIMARY KEY `D`, `E`)";
8728     r = run_query(hdb, 0, query);
8729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8730
8731     query = "SELECT * FROM `T`";
8732     r = MsiDatabaseOpenView(hdb, query, &view);
8733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8734
8735     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8737
8738     sz = MAX_PATH;
8739     lstrcpyA(buf, "kiwi");
8740     r = MsiRecordGetString(rec, 1, buf, &sz);
8741     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8742     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8743
8744     sz = MAX_PATH;
8745     lstrcpyA(buf, "kiwi");
8746     r = MsiRecordGetString(rec, 2, buf, &sz);
8747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8748     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8749
8750     sz = MAX_PATH;
8751     lstrcpyA(buf, "kiwi");
8752     r = MsiRecordGetString(rec, 3, buf, &sz);
8753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8754     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8755
8756     sz = MAX_PATH;
8757     lstrcpyA(buf, "kiwi");
8758     r = MsiRecordGetString(rec, 4, buf, &sz);
8759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8760     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8761
8762     sz = MAX_PATH;
8763     lstrcpyA(buf, "kiwi");
8764     r = MsiRecordGetString(rec, 5, buf, &sz);
8765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8766     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8767
8768     MsiCloseHandle(rec);
8769
8770     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8772
8773     sz = MAX_PATH;
8774     lstrcpyA(buf, "kiwi");
8775     r = MsiRecordGetString(rec, 1, buf, &sz);
8776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8777     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8778
8779     sz = MAX_PATH;
8780     lstrcpyA(buf, "kiwi");
8781     r = MsiRecordGetString(rec, 2, buf, &sz);
8782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8783     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8784
8785     sz = MAX_PATH;
8786     lstrcpyA(buf, "kiwi");
8787     r = MsiRecordGetString(rec, 3, buf, &sz);
8788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8789     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8790
8791     sz = MAX_PATH;
8792     lstrcpyA(buf, "kiwi");
8793     r = MsiRecordGetString(rec, 4, buf, &sz);
8794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8795     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8796
8797     sz = MAX_PATH;
8798     lstrcpyA(buf, "kiwi");
8799     r = MsiRecordGetString(rec, 5, buf, &sz);
8800     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8801     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8802
8803     MsiCloseHandle(rec);
8804     MsiViewClose(view);
8805     MsiCloseHandle(view);
8806
8807     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8808             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8809     r = run_query(hdb, 0, query);
8810     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8811
8812     query = "SELECT * FROM `T`";
8813     r = do_query(hdb, query, &rec);
8814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8815
8816     sz = MAX_PATH;
8817     lstrcpyA(buf, "kiwi");
8818     r = MsiRecordGetString(rec, 1, buf, &sz);
8819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8820     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8821
8822     r = MsiRecordGetInteger(rec, 2);
8823     ok(r == 3, "Expected 3, got %d\n", r);
8824
8825     sz = MAX_PATH;
8826     lstrcpyA(buf, "kiwi");
8827     r = MsiRecordGetString(rec, 3, buf, &sz);
8828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8829     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8830
8831     r = MsiRecordGetInteger(rec, 4);
8832     ok(r == 2, "Expected 2, got %d\n", r);
8833
8834     r = MsiRecordGetInteger(rec, 5);
8835     ok(r == 1, "Expected 1, got %d\n", r);
8836
8837     MsiCloseHandle(rec);
8838
8839     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8840     r = MsiDatabaseOpenView(hdb, query, &view);
8841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8842     r = MsiViewExecute(view, 0);
8843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8844
8845     r = MsiViewFetch(view, &rec);
8846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8847
8848     sz = MAX_PATH;
8849     lstrcpyA(buf, "kiwi");
8850     r = MsiRecordGetString(rec, 1, buf, &sz);
8851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8852     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8853
8854     r = MsiRecordGetInteger(rec, 2);
8855     ok(r == 1, "Expected 1, got %d\n", r);
8856
8857     sz = MAX_PATH;
8858     lstrcpyA(buf, "kiwi");
8859     r = MsiRecordGetString(rec, 3, buf, &sz);
8860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8861     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8862
8863     MsiCloseHandle(rec);
8864
8865     r = MsiViewFetch(view, &rec);
8866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8867
8868     sz = MAX_PATH;
8869     lstrcpyA(buf, "kiwi");
8870     r = MsiRecordGetString(rec, 1, buf, &sz);
8871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8872     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8873
8874     r = MsiRecordGetInteger(rec, 2);
8875     ok(r == 2, "Expected 2, got %d\n", r);
8876
8877     sz = MAX_PATH;
8878     lstrcpyA(buf, "kiwi");
8879     r = MsiRecordGetString(rec, 3, buf, &sz);
8880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8881     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8882
8883     MsiCloseHandle(rec);
8884
8885     r = MsiViewFetch(view, &rec);
8886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8887
8888     sz = MAX_PATH;
8889     lstrcpyA(buf, "kiwi");
8890     r = MsiRecordGetString(rec, 1, buf, &sz);
8891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8892     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8893
8894     r = MsiRecordGetInteger(rec, 2);
8895     ok(r == 3, "Expected 3, got %d\n", r);
8896
8897     sz = MAX_PATH;
8898     lstrcpyA(buf, "kiwi");
8899     r = MsiRecordGetString(rec, 3, buf, &sz);
8900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8901     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8902
8903     MsiCloseHandle(rec);
8904
8905     r = MsiViewFetch(view, &rec);
8906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8907
8908     sz = MAX_PATH;
8909     lstrcpyA(buf, "kiwi");
8910     r = MsiRecordGetString(rec, 1, buf, &sz);
8911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8912     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8913
8914     r = MsiRecordGetInteger(rec, 2);
8915     ok(r == 4, "Expected 4, got %d\n", r);
8916
8917     sz = MAX_PATH;
8918     lstrcpyA(buf, "kiwi");
8919     r = MsiRecordGetString(rec, 3, buf, &sz);
8920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8921     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8922
8923     MsiCloseHandle(rec);
8924
8925     r = MsiViewFetch(view, &rec);
8926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8927
8928     sz = MAX_PATH;
8929     lstrcpyA(buf, "kiwi");
8930     r = MsiRecordGetString(rec, 1, buf, &sz);
8931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8932     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8933
8934     r = MsiRecordGetInteger(rec, 2);
8935     ok(r == 5, "Expected 5, got %d\n", r);
8936
8937     sz = MAX_PATH;
8938     lstrcpyA(buf, "kiwi");
8939     r = MsiRecordGetString(rec, 3, buf, &sz);
8940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8941     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8942
8943     MsiCloseHandle(rec);
8944
8945     r = MsiViewFetch(view, &rec);
8946     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8947
8948     MsiViewClose(view);
8949     MsiCloseHandle(view);
8950
8951     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8952             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8953             "PRIMARY KEY `C`, `A`, `D`)";
8954     r = run_query(hdb, 0, query);
8955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8956
8957     query = "SELECT * FROM `Z`";
8958     r = MsiDatabaseOpenView(hdb, query, &view);
8959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8960
8961     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8963
8964     sz = MAX_PATH;
8965     lstrcpyA(buf, "kiwi");
8966     r = MsiRecordGetString(rec, 1, buf, &sz);
8967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8968     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8969
8970     sz = MAX_PATH;
8971     lstrcpyA(buf, "kiwi");
8972     r = MsiRecordGetString(rec, 2, buf, &sz);
8973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8974     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8975
8976     sz = MAX_PATH;
8977     lstrcpyA(buf, "kiwi");
8978     r = MsiRecordGetString(rec, 3, buf, &sz);
8979     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8980     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8981
8982     sz = MAX_PATH;
8983     lstrcpyA(buf, "kiwi");
8984     r = MsiRecordGetString(rec, 4, buf, &sz);
8985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8986     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8987
8988     sz = MAX_PATH;
8989     lstrcpyA(buf, "kiwi");
8990     r = MsiRecordGetString(rec, 5, buf, &sz);
8991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8992     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8993
8994     MsiCloseHandle(rec);
8995
8996     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8998
8999     sz = MAX_PATH;
9000     lstrcpyA(buf, "kiwi");
9001     r = MsiRecordGetString(rec, 1, buf, &sz);
9002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9003     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9004
9005     sz = MAX_PATH;
9006     lstrcpyA(buf, "kiwi");
9007     r = MsiRecordGetString(rec, 2, buf, &sz);
9008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9009     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9010
9011     sz = MAX_PATH;
9012     lstrcpyA(buf, "kiwi");
9013     r = MsiRecordGetString(rec, 3, buf, &sz);
9014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9015     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9016
9017     sz = MAX_PATH;
9018     lstrcpyA(buf, "kiwi");
9019     r = MsiRecordGetString(rec, 4, buf, &sz);
9020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9021     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9022
9023     sz = MAX_PATH;
9024     lstrcpyA(buf, "kiwi");
9025     r = MsiRecordGetString(rec, 5, buf, &sz);
9026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9027     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9028
9029     MsiCloseHandle(rec);
9030     MsiViewClose(view);
9031     MsiCloseHandle(view);
9032
9033     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
9034             "VALUES ( 1, 2, 'a', 3, 'bc' )";
9035     r = run_query(hdb, 0, query);
9036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9037
9038     query = "SELECT * FROM `Z`";
9039     r = do_query(hdb, query, &rec);
9040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9041
9042     r = MsiRecordGetInteger(rec, 1);
9043     ok(r == 2, "Expected 2, got %d\n", r);
9044
9045     sz = MAX_PATH;
9046     lstrcpyA(buf, "kiwi");
9047     r = MsiRecordGetString(rec, 2, buf, &sz);
9048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9049     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
9050
9051     sz = MAX_PATH;
9052     lstrcpyA(buf, "kiwi");
9053     r = MsiRecordGetString(rec, 3, buf, &sz);
9054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9055     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
9056
9057     r = MsiRecordGetInteger(rec, 4);
9058     ok(r == 3, "Expected 3, got %d\n", r);
9059
9060     r = MsiRecordGetInteger(rec, 5);
9061     ok(r == 1, "Expected 1, got %d\n", r);
9062
9063     MsiCloseHandle(rec);
9064
9065     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
9066     r = MsiDatabaseOpenView(hdb, query, &view);
9067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9068     r = MsiViewExecute(view, 0);
9069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9070
9071     r = MsiViewFetch(view, &rec);
9072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9073
9074     sz = MAX_PATH;
9075     lstrcpyA(buf, "kiwi");
9076     r = MsiRecordGetString(rec, 1, buf, &sz);
9077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9078     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9079
9080     r = MsiRecordGetInteger(rec, 2);
9081     ok(r == 1, "Expected 1, got %d\n", r);
9082
9083     sz = MAX_PATH;
9084     lstrcpyA(buf, "kiwi");
9085     r = MsiRecordGetString(rec, 3, buf, &sz);
9086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9087     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9088
9089     MsiCloseHandle(rec);
9090
9091     r = MsiViewFetch(view, &rec);
9092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9093
9094     sz = MAX_PATH;
9095     lstrcpyA(buf, "kiwi");
9096     r = MsiRecordGetString(rec, 1, buf, &sz);
9097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9098     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9099
9100     r = MsiRecordGetInteger(rec, 2);
9101     ok(r == 2, "Expected 2, got %d\n", r);
9102
9103     sz = MAX_PATH;
9104     lstrcpyA(buf, "kiwi");
9105     r = MsiRecordGetString(rec, 3, buf, &sz);
9106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9107     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9108
9109     MsiCloseHandle(rec);
9110
9111     r = MsiViewFetch(view, &rec);
9112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9113
9114     sz = MAX_PATH;
9115     lstrcpyA(buf, "kiwi");
9116     r = MsiRecordGetString(rec, 1, buf, &sz);
9117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9118     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9119
9120     r = MsiRecordGetInteger(rec, 2);
9121     ok(r == 3, "Expected 3, got %d\n", r);
9122
9123     sz = MAX_PATH;
9124     lstrcpyA(buf, "kiwi");
9125     r = MsiRecordGetString(rec, 3, buf, &sz);
9126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9127     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9128
9129     MsiCloseHandle(rec);
9130
9131     r = MsiViewFetch(view, &rec);
9132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9133
9134     sz = MAX_PATH;
9135     lstrcpyA(buf, "kiwi");
9136     r = MsiRecordGetString(rec, 1, buf, &sz);
9137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9138     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9139
9140     r = MsiRecordGetInteger(rec, 2);
9141     ok(r == 4, "Expected 4, got %d\n", r);
9142
9143     sz = MAX_PATH;
9144     lstrcpyA(buf, "kiwi");
9145     r = MsiRecordGetString(rec, 3, buf, &sz);
9146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9147     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9148
9149     MsiCloseHandle(rec);
9150
9151     r = MsiViewFetch(view, &rec);
9152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9153
9154     sz = MAX_PATH;
9155     lstrcpyA(buf, "kiwi");
9156     r = MsiRecordGetString(rec, 1, buf, &sz);
9157     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9158     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9159
9160     r = MsiRecordGetInteger(rec, 2);
9161     ok(r == 5, "Expected 5, got %d\n", r);
9162
9163     sz = MAX_PATH;
9164     lstrcpyA(buf, "kiwi");
9165     r = MsiRecordGetString(rec, 3, buf, &sz);
9166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9167     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9168
9169     MsiCloseHandle(rec);
9170
9171     r = MsiViewFetch(view, &rec);
9172     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9173
9174     MsiViewClose(view);
9175     MsiCloseHandle(view);
9176
9177     MsiCloseHandle(hdb);
9178     DeleteFileA(msifile);
9179 }
9180
9181 static void test_createtable(void)
9182 {
9183     MSIHANDLE hdb, htab = 0, hrec = 0;
9184     LPCSTR query;
9185     UINT res;
9186     DWORD size;
9187     char buffer[0x20];
9188
9189     hdb = create_db();
9190     ok(hdb, "failed to create db\n");
9191
9192     query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9193     res = MsiDatabaseOpenView( hdb, query, &htab );
9194     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9195     if(res == ERROR_SUCCESS )
9196     {
9197         res = MsiViewExecute( htab, hrec );
9198         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9199
9200         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9201         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9202
9203         size = sizeof(buffer);
9204         res = MsiRecordGetString(hrec, 1, buffer, &size );
9205         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9206         MsiCloseHandle( hrec );
9207
9208         res = MsiViewClose( htab );
9209         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9210
9211         res = MsiCloseHandle( htab );
9212         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9213     }
9214
9215     query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9216     res = MsiDatabaseOpenView( hdb, query, &htab );
9217     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9218     if(res == ERROR_SUCCESS )
9219     {
9220         res = MsiViewExecute( htab, 0 );
9221         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9222
9223         res = MsiViewClose( htab );
9224         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9225
9226         res = MsiCloseHandle( htab );
9227         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9228
9229         query = "SELECT * FROM `a`";
9230         res = MsiDatabaseOpenView( hdb, query, &htab );
9231         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9232
9233         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9234         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9235
9236         buffer[0] = 0;
9237         size = sizeof(buffer);
9238         res = MsiRecordGetString(hrec, 1, buffer, &size );
9239         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9240         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9241         MsiCloseHandle( hrec );
9242
9243         res = MsiViewClose( htab );
9244         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9245
9246         res = MsiCloseHandle( htab );
9247         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9248
9249         res = MsiDatabaseCommit(hdb);
9250         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9251
9252         res = MsiCloseHandle(hdb);
9253         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9254
9255         res = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
9256         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9257
9258         query = "SELECT * FROM `a`";
9259         res = MsiDatabaseOpenView( hdb, query, &htab );
9260         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9261
9262         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9263         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9264
9265         buffer[0] = 0;
9266         size = sizeof(buffer);
9267         res = MsiRecordGetString(hrec, 1, buffer, &size );
9268         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9269         todo_wine ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9270
9271         res = MsiCloseHandle( hrec );
9272         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9273
9274         res = MsiViewClose( htab );
9275         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9276
9277         res = MsiCloseHandle( htab );
9278         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9279     }
9280
9281     res = MsiDatabaseCommit(hdb);
9282     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9283
9284     res = MsiCloseHandle(hdb);
9285     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9286
9287     DeleteFileA(msifile);
9288 }
9289
9290 static void test_embedded_nulls(void)
9291 {
9292     static const char control_table[] =
9293         "Dialog\tText\n"
9294         "s72\tL0\n"
9295         "Control\tDialog\n"
9296         "LicenseAgreementDlg\ttext\x11\x19text\0text";
9297     UINT r, sz;
9298     MSIHANDLE hdb, hrec;
9299     char buffer[32];
9300
9301     r = MsiOpenDatabaseA( msifile, MSIDBOPEN_CREATE, &hdb );
9302     ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
9303
9304     GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
9305     write_file( "temp_file", control_table, sizeof(control_table) );
9306     r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
9307     ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
9308     DeleteFileA( "temp_file" );
9309
9310     r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
9311     ok( r == ERROR_SUCCESS, "query failed %u\n", r );
9312
9313     buffer[0] = 0;
9314     sz = sizeof(buffer);
9315     r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
9316     ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
9317     ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
9318
9319     MsiCloseHandle( hrec );
9320     MsiCloseHandle( hdb );
9321     DeleteFileA( msifile );
9322 }
9323
9324 START_TEST(db)
9325 {
9326     test_msidatabase();
9327     test_msiinsert();
9328     test_msidecomposedesc();
9329     test_msibadqueries();
9330     test_viewmodify();
9331     test_viewgetcolumninfo();
9332     test_getcolinfo();
9333     test_msiexport();
9334     test_longstrings();
9335     test_streamtable();
9336     test_binary();
9337     test_where_not_in_selected();
9338     test_where();
9339     test_msiimport();
9340     test_binary_import();
9341     test_markers();
9342     test_handle_limit();
9343     test_try_transform();
9344     test_join();
9345     test_temporary_table();
9346     test_alter();
9347     test_integers();
9348     test_update();
9349     test_special_tables();
9350     test_tables_order();
9351     test_rows_order();
9352     test_select_markers();
9353     test_viewmodify_update();
9354     test_viewmodify_assign();
9355     test_stringtable();
9356     test_viewmodify_delete();
9357     test_defaultdatabase();
9358     test_order();
9359     test_viewmodify_delete_temporary();
9360     test_deleterow();
9361     test_quotes();
9362     test_carriagereturn();
9363     test_noquotes();
9364     test_forcecodepage();
9365     test_viewmodify_refresh();
9366     test_where_viewmodify();
9367     test_storages_table();
9368     test_dbtopackage();
9369     test_droptable();
9370     test_dbmerge();
9371     test_select_with_tablenames();
9372     test_insertorder();
9373     test_columnorder();
9374     test_suminfo_import();
9375     test_createtable();
9376     test_collation();
9377     test_embedded_nulls();
9378 }