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