hlink: Site data should only be set if the hlink has an HlinkSite.
[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     if (r == ERROR_FUNCTION_FAILED)
2190     {
2191         /* win9x doesn't handle this case */
2192         skip("endlines not handled correctly.\n");
2193         MsiCloseHandle(hdb);
2194         DeleteFileA(msifile);
2195         return;
2196     }
2197
2198     r = add_table_to_db(hdb, endlines2);
2199     ok(r == ERROR_FUNCTION_FAILED,
2200        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2201
2202     query = "SELECT * FROM `TestTable`";
2203     r = MsiDatabaseOpenView(hdb, query, &view);
2204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2205
2206     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2207     count = MsiRecordGetFieldCount(rec);
2208     ok(count == 9, "Expected 9, got %d\n", count);
2209     ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2210     ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2211     ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2212     ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2213     ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2214     ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2215     ok(check_record(rec, 7, "String"), "Expected String\n");
2216     ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2217     ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2218     MsiCloseHandle(rec);
2219
2220     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2221     count = MsiRecordGetFieldCount(rec);
2222     ok(count == 9, "Expected 9, got %d\n", count);
2223     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2224     ok(check_record(rec, 2, "i2"), "Expected i2\n");
2225     ok(check_record(rec, 3, "i2"), "Expected i2\n");
2226     ok(check_record(rec, 4, "I2"), "Expected I2\n");
2227     ok(check_record(rec, 5, "i4"), "Expected i4\n");
2228     ok(check_record(rec, 6, "I4"), "Expected I4\n");
2229     ok(check_record(rec, 7, "S255"), "Expected S255\n");
2230     ok(check_record(rec, 8, "S0"), "Expected S0\n");
2231     ok(check_record(rec, 9, "s0"), "Expected s0\n");
2232     MsiCloseHandle(rec);
2233
2234     query = "SELECT * FROM `TestTable`";
2235     r = do_query(hdb, query, &rec);
2236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2237     ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2238     ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2239     ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2240     ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2241
2242     i = MsiRecordGetInteger(rec, 2);
2243     ok(i == 5, "Expected 5, got %d\n", i);
2244
2245     i = MsiRecordGetInteger(rec, 3);
2246     ok(i == 2, "Expected 2, got %d\n", i);
2247
2248     i = MsiRecordGetInteger(rec, 4);
2249     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2250
2251     i = MsiRecordGetInteger(rec, 5);
2252     ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2253
2254     i = MsiRecordGetInteger(rec, 6);
2255     ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2256
2257     MsiCloseHandle(rec);
2258     MsiViewClose(view);
2259     MsiCloseHandle(view);
2260
2261     query = "SELECT * FROM `TwoPrimary`";
2262     r = MsiDatabaseOpenView(hdb, query, &view);
2263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2264
2265     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2266     count = MsiRecordGetFieldCount(rec);
2267     ok(count == 2, "Expected 2, got %d\n", count);
2268     ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2269     ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2270
2271     MsiCloseHandle(rec);
2272
2273     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2274     count = MsiRecordGetFieldCount(rec);
2275     ok(count == 2, "Expected 2, got %d\n", count);
2276     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2277     ok(check_record(rec, 2, "s255"), "Expected s255\n");
2278     MsiCloseHandle(rec);
2279
2280     r = MsiViewExecute(view, 0);
2281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2282
2283     r = MsiViewFetch(view, &rec);
2284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2285
2286     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2287     ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2288
2289     MsiCloseHandle(rec);
2290
2291     r = MsiViewFetch(view, &rec);
2292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2293
2294     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2295     ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2296
2297     MsiCloseHandle(rec);
2298
2299     r = MsiViewFetch(view, &rec);
2300     ok(r == ERROR_NO_MORE_ITEMS,
2301        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2302
2303     r = MsiViewClose(view);
2304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2305
2306     MsiCloseHandle(view);
2307
2308     query = "SELECT * FROM `Table`";
2309     r = MsiDatabaseOpenView(hdb, query, &view);
2310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2311
2312     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2313     count = MsiRecordGetFieldCount(rec);
2314     ok(count == 6, "Expected 6, got %d\n", count);
2315     ok(check_record(rec, 1, "A"), "Expected A\n");
2316     ok(check_record(rec, 2, "B"), "Expected B\n");
2317     ok(check_record(rec, 3, "C"), "Expected C\n");
2318     ok(check_record(rec, 4, "D"), "Expected D\n");
2319     ok(check_record(rec, 5, "E"), "Expected E\n");
2320     ok(check_record(rec, 6, "F"), "Expected F\n");
2321     MsiCloseHandle(rec);
2322
2323     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2324     count = MsiRecordGetFieldCount(rec);
2325     ok(count == 6, "Expected 6, got %d\n", count);
2326     ok(check_record(rec, 1, "s72"), "Expected s72\n");
2327     ok(check_record(rec, 2, "s72"), "Expected s72\n");
2328     ok(check_record(rec, 3, "s72"), "Expected s72\n");
2329     ok(check_record(rec, 4, "s72"), "Expected s72\n");
2330     ok(check_record(rec, 5, "s72"), "Expected s72\n");
2331     ok(check_record(rec, 6, "s72"), "Expected s72\n");
2332     MsiCloseHandle(rec);
2333
2334     MsiViewClose(view);
2335     MsiCloseHandle(view);
2336
2337     query = "SELECT * FROM `Table`";
2338     r = MsiDatabaseOpenView(hdb, query, &view);
2339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2340
2341     r = MsiViewExecute(view, 0);
2342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2343
2344     r = MsiViewFetch(view, &rec);
2345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2346     ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2347     ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2348     ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2349     ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2350     ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2351     ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2352
2353     MsiCloseHandle(rec);
2354
2355     r = MsiViewFetch(view, &rec);
2356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2357     ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2358     ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2359     ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2360     ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2361     ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2362     ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2363
2364     MsiCloseHandle(rec);
2365
2366     r = MsiViewFetch(view, &rec);
2367     ok(r == ERROR_NO_MORE_ITEMS,
2368        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2369
2370     MsiViewClose(view);
2371     MsiCloseHandle(view);
2372     MsiCloseHandle(hdb);
2373     DeleteFileA(msifile);
2374 }
2375
2376 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2377                                      "s72\tV0\r\n"
2378                                      "Binary\tName\r\n"
2379                                      "filename1\tfilename1.ibd\r\n";
2380
2381 static void test_binary_import(void)
2382 {
2383     MSIHANDLE hdb = 0, rec;
2384     char file[MAX_PATH];
2385     char buf[MAX_PATH];
2386     char path[MAX_PATH];
2387     DWORD size;
2388     LPCSTR query;
2389     UINT r;
2390
2391     /* create files to import */
2392     write_file("bin_import.idt", bin_import_dat,
2393           (sizeof(bin_import_dat) - 1) * sizeof(char));
2394     CreateDirectory("bin_import", NULL);
2395     create_file_data("bin_import/filename1.ibd", "just some words", 15);
2396
2397     /* import files into database */
2398     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
2399     ok( r == ERROR_SUCCESS , "Failed to open database\n");
2400
2401     GetCurrentDirectory(MAX_PATH, path);
2402     r = MsiDatabaseImport(hdb, path, "bin_import.idt");
2403     ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2404
2405     /* read file from the Binary table */
2406     query = "SELECT * FROM `Binary`";
2407     r = do_query(hdb, query, &rec);
2408     ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2409
2410     size = MAX_PATH;
2411     r = MsiRecordGetString(rec, 1, file, &size);
2412     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2413     ok(!lstrcmp(file, "filename1"), "Expected 'filename1', got %s\n", file);
2414
2415     size = MAX_PATH;
2416     memset(buf, 0, MAX_PATH);
2417     r = MsiRecordReadStream(rec, 2, buf, &size);
2418     ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2419     ok(!lstrcmp(buf, "just some words"),
2420         "Expected 'just some words', got %s\n", buf);
2421
2422     r = MsiCloseHandle(rec);
2423     ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2424
2425     r = MsiCloseHandle(hdb);
2426     ok(r == ERROR_SUCCESS , "Failed to close database\n");
2427
2428     DeleteFile("bin_import/filename1.ibd");
2429     RemoveDirectory("bin_import");
2430     DeleteFile("bin_import.idt");
2431 }
2432
2433 static void test_markers(void)
2434 {
2435     MSIHANDLE hdb, rec;
2436     LPCSTR query;
2437     UINT r;
2438
2439     hdb = create_db();
2440     ok( hdb, "failed to create db\n");
2441
2442     rec = MsiCreateRecord(3);
2443     MsiRecordSetString(rec, 1, "Table");
2444     MsiRecordSetString(rec, 2, "Apples");
2445     MsiRecordSetString(rec, 3, "Oranges");
2446
2447     /* try a legit create */
2448     query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2449     r = run_query(hdb, 0, query);
2450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2451     MsiCloseHandle(rec);
2452
2453     /* try table name as marker */
2454     rec = MsiCreateRecord(1);
2455     MsiRecordSetString(rec, 1, "Fable");
2456     query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2457     r = run_query(hdb, rec, query);
2458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2459
2460     /* verify that we just created a table called '?', not 'Fable' */
2461     r = try_query(hdb, "SELECT * from `Fable`");
2462     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2463
2464     r = try_query(hdb, "SELECT * from `?`");
2465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2466
2467     /* try table name as marker without backticks */
2468     MsiRecordSetString(rec, 1, "Mable");
2469     query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2470     r = run_query(hdb, rec, query);
2471     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2472
2473     /* try one column name as marker */
2474     MsiRecordSetString(rec, 1, "One");
2475     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2476     r = run_query(hdb, rec, query);
2477     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2478     MsiCloseHandle(rec);
2479
2480     /* try column names as markers */
2481     rec = MsiCreateRecord(2);
2482     MsiRecordSetString(rec, 1, "One");
2483     MsiRecordSetString(rec, 2, "Two");
2484     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2485     r = run_query(hdb, rec, query);
2486     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2487     MsiCloseHandle(rec);
2488
2489     /* try names with backticks */
2490     rec = MsiCreateRecord(3);
2491     MsiRecordSetString(rec, 1, "One");
2492     MsiRecordSetString(rec, 2, "Two");
2493     MsiRecordSetString(rec, 3, "One");
2494     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2495     r = run_query(hdb, rec, query);
2496     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2497
2498     /* try names with backticks, minus definitions */
2499     query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2500     r = run_query(hdb, rec, query);
2501     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2502
2503     /* try names without backticks */
2504     query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2505     r = run_query(hdb, rec, query);
2506     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2507     MsiCloseHandle(rec);
2508
2509     /* try one long marker */
2510     rec = MsiCreateRecord(1);
2511     MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2512     query = "CREATE TABLE `Mable` ( ? )";
2513     r = run_query(hdb, rec, query);
2514     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2515     MsiCloseHandle(rec);
2516
2517     /* try all names as markers */
2518     rec = MsiCreateRecord(4);
2519     MsiRecordSetString(rec, 1, "Mable");
2520     MsiRecordSetString(rec, 2, "One");
2521     MsiRecordSetString(rec, 3, "Two");
2522     MsiRecordSetString(rec, 4, "One");
2523     query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2524     r = run_query(hdb, rec, query);
2525     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2526     MsiCloseHandle(rec);
2527
2528     /* try a legit insert */
2529     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2530     r = run_query(hdb, 0, query);
2531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2532
2533     r = try_query(hdb, "SELECT * from `Table`");
2534     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2535
2536     /* try values as markers */
2537     rec = MsiCreateRecord(2);
2538     MsiRecordSetInteger(rec, 1, 4);
2539     MsiRecordSetString(rec, 2, "hi");
2540     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2541     r = run_query(hdb, rec, query);
2542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2543     MsiCloseHandle(rec);
2544
2545     /* try column names and values as markers */
2546     rec = MsiCreateRecord(4);
2547     MsiRecordSetString(rec, 1, "One");
2548     MsiRecordSetString(rec, 2, "Two");
2549     MsiRecordSetInteger(rec, 3, 5);
2550     MsiRecordSetString(rec, 4, "hi");
2551     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2552     r = run_query(hdb, rec, query);
2553     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2554     MsiCloseHandle(rec);
2555
2556     /* try column names as markers */
2557     rec = MsiCreateRecord(2);
2558     MsiRecordSetString(rec, 1, "One");
2559     MsiRecordSetString(rec, 2, "Two");
2560     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2561     r = run_query(hdb, rec, query);
2562     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2563     MsiCloseHandle(rec);
2564
2565     /* try table name as a marker */
2566     rec = MsiCreateRecord(1);
2567     MsiRecordSetString(rec, 1, "Table");
2568     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2569     r = run_query(hdb, rec, query);
2570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2571     MsiCloseHandle(rec);
2572
2573     /* try table name and values as markers */
2574     rec = MsiCreateRecord(3);
2575     MsiRecordSetString(rec, 1, "Table");
2576     MsiRecordSetInteger(rec, 2, 10);
2577     MsiRecordSetString(rec, 3, "haha");
2578     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2579     r = run_query(hdb, rec, query);
2580     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2581     MsiCloseHandle(rec);
2582
2583     /* try all markers */
2584     rec = MsiCreateRecord(5);
2585     MsiRecordSetString(rec, 1, "Table");
2586     MsiRecordSetString(rec, 1, "One");
2587     MsiRecordSetString(rec, 1, "Two");
2588     MsiRecordSetInteger(rec, 2, 10);
2589     MsiRecordSetString(rec, 3, "haha");
2590     query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2591     r = run_query(hdb, rec, query);
2592     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2593     MsiCloseHandle(rec);
2594
2595     /* insert an integer as a string */
2596     rec = MsiCreateRecord(2);
2597     MsiRecordSetString(rec, 1, "11");
2598     MsiRecordSetString(rec, 2, "hi");
2599     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2600     r = run_query(hdb, rec, query);
2601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2602     MsiCloseHandle(rec);
2603
2604     /* leave off the '' for the string */
2605     rec = MsiCreateRecord(2);
2606     MsiRecordSetInteger(rec, 1, 12);
2607     MsiRecordSetString(rec, 2, "hi");
2608     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2609     r = run_query(hdb, rec, query);
2610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2611     MsiCloseHandle(rec);
2612
2613     MsiCloseHandle(hdb);
2614     DeleteFileA(msifile);
2615 }
2616
2617 #define MY_NVIEWS 4000    /* Largest installer I've seen uses < 2k */
2618 static void test_handle_limit(void)
2619 {
2620     int i;
2621     MSIHANDLE hdb;
2622     MSIHANDLE hviews[MY_NVIEWS];
2623     UINT r;
2624
2625     /* create an empty db */
2626     hdb = create_db();
2627     ok( hdb, "failed to create db\n");
2628
2629     memset(hviews, 0, sizeof(hviews));
2630
2631     for (i=0; i<MY_NVIEWS; i++) {
2632         static char szQueryBuf[256] = "SELECT * from `_Tables`";
2633         hviews[i] = 0xdeadbeeb;
2634         r = MsiDatabaseOpenView(hdb, szQueryBuf, &hviews[i]);
2635         if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 
2636             hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2637             break;
2638     }
2639
2640     ok( i == MY_NVIEWS, "problem opening views\n");
2641
2642     for (i=0; i<MY_NVIEWS; i++) {
2643         if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2644             MsiViewClose(hviews[i]);
2645             r = MsiCloseHandle(hviews[i]);
2646             if (r != ERROR_SUCCESS)
2647                 break;
2648         }
2649     }
2650
2651     ok( i == MY_NVIEWS, "problem closing views\n");
2652
2653     r = MsiCloseHandle(hdb);
2654     ok( r == ERROR_SUCCESS, "failed to close database\n");
2655 }
2656
2657 static void generate_transform(void)
2658 {
2659     MSIHANDLE hdb1, hdb2, hrec;
2660     LPCSTR query;
2661     UINT r;
2662
2663     /* start with two identical databases */
2664     CopyFile(msifile2, msifile, FALSE);
2665
2666     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb1 );
2667     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2668
2669     r = MsiDatabaseCommit( hdb1 );
2670     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2671
2672     r = MsiOpenDatabase(msifile2, MSIDBOPEN_READONLY, &hdb2 );
2673     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2674
2675     /* the transform between two identical database should be empty */
2676     r = MsiDatabaseGenerateTransform(hdb1, hdb2, NULL, 0, 0);
2677     todo_wine {
2678     ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2679     }
2680
2681     query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2682     r = run_query(hdb1, 0, query);
2683     ok(r == ERROR_SUCCESS, "failed to add table\n");
2684
2685     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2686     r = run_query(hdb1, 0, query);
2687     ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2688
2689     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2690     r = run_query(hdb1, 0, query);
2691     ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2692
2693     query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2694     r = run_query(hdb1, 0, query);
2695     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2696
2697     query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2698     r = run_query(hdb1, 0, query);
2699     ok(r == ERROR_SUCCESS, "failed to delete row\n");
2700
2701     hrec = MsiCreateRecord(2);
2702     r = MsiRecordSetInteger(hrec, 1, 1);
2703     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2704
2705     write_file("testdata.bin", "naengmyon", 9);
2706     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
2707     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2708
2709     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2710     r = run_query(hdb1, hrec, query);
2711     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2712
2713     MsiCloseHandle(hrec);
2714
2715     query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2716     r = run_query(hdb1, 0, query);
2717     ok(r == ERROR_SUCCESS, "failed to add column\n");
2718
2719     query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2720     r = run_query(hdb1, 0, query);
2721     ok(r == ERROR_SUCCESS, "failed to add column\n");
2722
2723     query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2724     r = run_query(hdb1, 0, query);
2725     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2726
2727     query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2728             "`Value` CHAR(0) PRIMARY KEY `Property`)";
2729     r = run_query(hdb1, 0, query);
2730     ok(r == ERROR_SUCCESS, "failed to add property table\n");
2731
2732     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2733     r = run_query(hdb1, 0, query);
2734     ok(r == ERROR_SUCCESS, "failed to add property\n");
2735
2736     /* database needs to be committed */
2737     MsiDatabaseCommit(hdb1);
2738
2739     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2740     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2741
2742     MsiCloseHandle( hdb1 );
2743     MsiCloseHandle( hdb2 );
2744
2745     DeleteFile("testdata.bin");
2746 }
2747
2748 /* data for generating a transform */
2749
2750 /* tables transform names - encoded as they would be in an msi database file */
2751 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2752 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2753 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2754 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2755 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2756 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2757 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2758 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2759 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2760
2761 /* data in each table */
2762 static const WCHAR data1[] = { /* AAR */
2763     0x0201, 0x0008, 0x8001,  /* 0x0201 = add row (1), two shorts */
2764     0x0201, 0x0009, 0x8002,
2765 };
2766 static const WCHAR data2[] = { /* _Columns */
2767     0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2768     0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2769     0x0401, 0x0005, 0x0000, 0x0006, 0xbdff,  /* 0x0401 = add row (1), 4 shorts */
2770     0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2771     0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2772     0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2773 };
2774 static const WCHAR data3[] = { /* _Tables */
2775     0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2776     0x0101, 0x000a,
2777 };
2778 static const char data4[] = /* _StringData */
2779     "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval";  /* all the strings squashed together */
2780 static const WCHAR data5[] = { /* _StringPool */
2781 /*  len, refs */
2782     0,   0,    /* string 0 ''    */
2783     3,   2,    /* string 1 'MOO' */
2784     3,   1,    /* string 2 'COW' */
2785     3,   1,    /* string 3 'PIG' */
2786     1,   1,    /* string 4 'c'   */
2787     3,   3,    /* string 5 'AAR' */
2788     3,   1,    /* string 6 'CAR' */
2789     3,   1,    /* string 7 'BAR' */
2790     2,   1,    /* string 8 'vw'  */
2791     3,   1,    /* string 9 'bmw' */
2792     8,   4,    /* string 10 'Property' */
2793     5,   1,    /* string 11 'Value' */
2794     4,   1,    /* string 12 'prop' */
2795     3,   1,    /* string 13 'val' */
2796 };
2797 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2798 static const WCHAR data6[] = { /* MOO */
2799     0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2800     0x0000, 0x8003,         /* delete row */
2801 };
2802
2803 static const WCHAR data7[] = { /* BINARY */
2804     0x0201, 0x8001, 0x0001,
2805 };
2806
2807 static const char data8[] =  /* stream data for the BINARY table */
2808     "naengmyon";
2809
2810 static const WCHAR data9[] = { /* Property */
2811     0x0201, 0x000c, 0x000d,
2812 };
2813
2814 static const struct {
2815     LPCWSTR name;
2816     const void *data;
2817     DWORD size;
2818 } table_transform_data[] =
2819 {
2820     { name1, data1, sizeof data1 },
2821     { name2, data2, sizeof data2 },
2822     { name3, data3, sizeof data3 },
2823     { name4, data4, sizeof data4 - 1 },
2824     { name5, data5, sizeof data5 },
2825     { name6, data6, sizeof data6 },
2826     { name7, data7, sizeof data7 },
2827     { name8, data8, sizeof data8 - 1 },
2828     { name9, data9, sizeof data9 },
2829 };
2830
2831 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2832
2833 static void generate_transform_manual(void)
2834 {
2835     IStorage *stg = NULL;
2836     IStream *stm;
2837     WCHAR name[0x20];
2838     HRESULT r;
2839     DWORD i, count;
2840     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2841
2842     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2843
2844     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2845
2846     r = StgCreateDocfile(name, mode, 0, &stg);
2847     ok(r == S_OK, "failed to create storage\n");
2848     if (!stg)
2849         return;
2850
2851     r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2852     ok(r == S_OK, "failed to set storage type\n");
2853
2854     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2855     {
2856         r = IStorage_CreateStream( stg, table_transform_data[i].name,
2857                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2858         if (FAILED(r))
2859         {
2860             ok(0, "failed to create stream %08x\n", r);
2861             continue;
2862         }
2863
2864         r = IStream_Write( stm, table_transform_data[i].data,
2865                           table_transform_data[i].size, &count );
2866         if (FAILED(r) || count != table_transform_data[i].size)
2867             ok(0, "failed to write stream\n");
2868         IStream_Release(stm);
2869     }
2870
2871     IStorage_Release(stg);
2872 }
2873
2874 static UINT set_summary_info(MSIHANDLE hdb)
2875 {
2876     UINT res;
2877     MSIHANDLE suminfo;
2878
2879     /* build summary info */
2880     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
2881     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2882
2883     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
2884                         "Installation Database");
2885     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2886
2887     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
2888                         "Installation Database");
2889     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2890
2891     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
2892                         "Wine Hackers");
2893     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2894
2895     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
2896                     ";1033,2057");
2897     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2898
2899     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
2900                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
2901     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2902
2903     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
2904     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2905
2906     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
2907     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2908
2909     res = MsiSummaryInfoPersist(suminfo);
2910     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
2911
2912     res = MsiCloseHandle( suminfo);
2913     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
2914
2915     return res;
2916 }
2917
2918 static MSIHANDLE create_package_db(LPCSTR filename)
2919 {
2920     MSIHANDLE hdb = 0;
2921     UINT res;
2922
2923     DeleteFile(msifile);
2924
2925     /* create an empty database */
2926     res = MsiOpenDatabase(filename, MSIDBOPEN_CREATE, &hdb );
2927     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
2928     if( res != ERROR_SUCCESS )
2929         return hdb;
2930
2931     res = MsiDatabaseCommit( hdb );
2932     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
2933
2934     res = set_summary_info(hdb);
2935
2936     res = create_directory_table(hdb);
2937     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
2938
2939     return hdb;
2940 }
2941
2942 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
2943 {
2944     UINT res;
2945     CHAR szPackage[12];
2946     MSIHANDLE hPackage;
2947
2948     sprintf(szPackage, "#%u", hdb);
2949     res = MsiOpenPackage(szPackage, &hPackage);
2950     if (res != ERROR_SUCCESS)
2951         return res;
2952
2953     res = MsiCloseHandle(hdb);
2954     if (res != ERROR_SUCCESS)
2955     {
2956         MsiCloseHandle(hPackage);
2957         return res;
2958     }
2959
2960     *handle = hPackage;
2961     return ERROR_SUCCESS;
2962 }
2963
2964 static void test_try_transform(void)
2965 {
2966     MSIHANDLE hdb, hview, hrec, hpkg = 0;
2967     LPCSTR query;
2968     UINT r;
2969     DWORD sz;
2970     char buffer[MAX_PATH];
2971
2972     DeleteFile(msifile);
2973     DeleteFile(mstfile);
2974
2975     /* create the database */
2976     hdb = create_package_db(msifile);
2977     ok(hdb, "Failed to create package db\n");
2978
2979     query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
2980     r = run_query(hdb, 0, query);
2981     ok(r == ERROR_SUCCESS, "failed to add table\n");
2982
2983     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
2984     r = run_query(hdb, 0, query);
2985     ok(r == ERROR_SUCCESS, "failed to add row\n");
2986
2987     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
2988     r = run_query(hdb, 0, query);
2989     ok(r == ERROR_SUCCESS, "failed to add row\n");
2990
2991     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
2992     r = run_query(hdb, 0, query);
2993     ok(r == ERROR_SUCCESS, "failed to add row\n");
2994
2995     query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
2996     r = run_query(hdb, 0, query);
2997     ok(r == ERROR_SUCCESS, "failed to add table\n");
2998
2999     hrec = MsiCreateRecord(2);
3000     r = MsiRecordSetInteger(hrec, 1, 2);
3001     ok(r == ERROR_SUCCESS, "failed to set integer\n");
3002
3003     write_file("testdata.bin", "lamyon", 6);
3004     r = MsiRecordSetStream(hrec, 2, "testdata.bin");
3005     ok(r == ERROR_SUCCESS, "failed to set stream\n");
3006
3007     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3008     r = run_query(hdb, hrec, query);
3009     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3010
3011     MsiCloseHandle(hrec);
3012
3013     r = MsiDatabaseCommit( hdb );
3014     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3015
3016     MsiCloseHandle( hdb );
3017     DeleteFileA("testdata.bin");
3018
3019     /*
3020      * Both these generate an equivalent transform,
3021      *  but the first doesn't work in Wine yet
3022      *  because MsiDatabaseGenerateTransform is unimplemented.
3023      */
3024     if (0)
3025         generate_transform();
3026     else
3027         generate_transform_manual();
3028
3029     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb );
3030     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3031
3032     r = MsiDatabaseApplyTransform( hdb, mstfile, 0 );
3033     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3034
3035     MsiDatabaseCommit( hdb );
3036
3037     /* check new values */
3038     hrec = 0;
3039     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3040     r = do_query(hdb, query, &hrec);
3041     ok(r == ERROR_SUCCESS, "select query failed\n");
3042     MsiCloseHandle(hrec);
3043
3044     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3045     hrec = 0;
3046     r = do_query(hdb, query, &hrec);
3047     ok(r == ERROR_SUCCESS, "select query failed\n");
3048     MsiCloseHandle(hrec);
3049
3050     /* check updated values */
3051     hrec = 0;
3052     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3053     r = do_query(hdb, query, &hrec);
3054     ok(r == ERROR_SUCCESS, "select query failed\n");
3055     MsiCloseHandle(hrec);
3056
3057     /* check unchanged value */
3058     hrec = 0;
3059     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3060     r = do_query(hdb, query, &hrec);
3061     ok(r == ERROR_SUCCESS, "select query failed\n");
3062     MsiCloseHandle(hrec);
3063
3064     /* check deleted value */
3065     hrec = 0;
3066     query = "select * from `MOO` where `NOO` = 3";
3067     r = do_query(hdb, query, &hrec);
3068     ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3069     if (hrec) MsiCloseHandle(hrec);
3070
3071     /* check added stream */
3072     hrec = 0;
3073     query = "select `BLOB` from `BINARY` where `ID` = 1";
3074     r = do_query(hdb, query, &hrec);
3075     ok(r == ERROR_SUCCESS, "select query failed\n");
3076
3077     /* check the contents of the stream */
3078     sz = sizeof buffer;
3079     r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3080     ok(r == ERROR_SUCCESS, "read stream failed\n");
3081     ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3082     ok(sz == 9, "stream data was wrong size\n");
3083     if (hrec) MsiCloseHandle(hrec);
3084
3085     /* check the validity of the table with a deleted row */
3086     hrec = 0;
3087     query = "select * from `MOO`";
3088     r = MsiDatabaseOpenView(hdb, query, &hview);
3089     ok(r == ERROR_SUCCESS, "open view failed\n");
3090
3091     r = MsiViewExecute(hview, 0);
3092     ok(r == ERROR_SUCCESS, "view execute failed\n");
3093
3094     r = MsiViewFetch(hview, &hrec);
3095     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3096
3097     r = MsiRecordGetInteger(hrec, 1);
3098     ok(r == 1, "Expected 1, got %d\n", r);
3099
3100     sz = sizeof buffer;
3101     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3102     ok(r == ERROR_SUCCESS, "record get string failed\n");
3103     ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3104
3105     r = MsiRecordGetInteger(hrec, 3);
3106     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3107
3108     r = MsiRecordGetInteger(hrec, 4);
3109     ok(r == 5, "Expected 5, got %d\n", r);
3110
3111     MsiCloseHandle(hrec);
3112
3113     r = MsiViewFetch(hview, &hrec);
3114     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3115
3116     r = MsiRecordGetInteger(hrec, 1);
3117     ok(r == 2, "Expected 2, got %d\n", r);
3118
3119     sz = sizeof buffer;
3120     r = MsiRecordGetString(hrec, 2, buffer, &sz);
3121     ok(r == ERROR_SUCCESS, "record get string failed\n");
3122     ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3123
3124     r = MsiRecordGetInteger(hrec, 3);
3125     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3126
3127     r = MsiRecordGetInteger(hrec, 4);
3128     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3129
3130     MsiCloseHandle(hrec);
3131
3132     r = MsiViewFetch(hview, &hrec);
3133     ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3134
3135     MsiCloseHandle(hrec);
3136     MsiViewClose(hview);
3137     MsiCloseHandle(hview);
3138
3139     /* check that the property was added */
3140     r = package_from_db(hdb, &hpkg);
3141     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3142     {
3143         skip("Not enough rights to perform tests\n");
3144         goto error;
3145     }
3146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3147
3148     sz = MAX_PATH;
3149     r = MsiGetProperty(hpkg, "prop", buffer, &sz);
3150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3151     ok(!lstrcmp(buffer, "val"), "Expected val, got %s\n", buffer);
3152
3153     MsiCloseHandle(hpkg);
3154
3155 error:
3156     MsiCloseHandle(hdb);
3157     DeleteFile(msifile);
3158     DeleteFile(mstfile);
3159 }
3160
3161 struct join_res
3162 {
3163     const CHAR one[MAX_PATH];
3164     const CHAR two[MAX_PATH];
3165 };
3166
3167 struct join_res_4col
3168 {
3169     const CHAR one[MAX_PATH];
3170     const CHAR two[MAX_PATH];
3171     const CHAR three[MAX_PATH];
3172     const CHAR four[MAX_PATH];
3173 };
3174
3175 struct join_res_uint
3176 {
3177     UINT one;
3178     UINT two;
3179     UINT three;
3180     UINT four;
3181     UINT five;
3182     UINT six;
3183 };
3184
3185 static const struct join_res join_res_first[] =
3186 {
3187     { "alveolar", "procerus" },
3188     { "septum", "procerus" },
3189     { "septum", "nasalis" },
3190     { "ramus", "nasalis" },
3191     { "malar", "mentalis" },
3192 };
3193
3194 static const struct join_res join_res_second[] =
3195 {
3196     { "nasal", "septum" },
3197     { "mandible", "ramus" },
3198 };
3199
3200 static const struct join_res join_res_third[] =
3201 {
3202     { "msvcp.dll", "abcdefgh" },
3203     { "msvcr.dll", "ijklmnop" },
3204 };
3205
3206 static const struct join_res join_res_fourth[] =
3207 {
3208     { "msvcp.dll.01234", "single.dll.31415" },
3209 };
3210
3211 static const struct join_res join_res_fifth[] =
3212 {
3213     { "malar", "procerus" },
3214 };
3215
3216 static const struct join_res join_res_sixth[] =
3217 {
3218     { "malar", "procerus" },
3219     { "malar", "procerus" },
3220     { "malar", "nasalis" },
3221     { "malar", "nasalis" },
3222     { "malar", "nasalis" },
3223     { "malar", "mentalis" },
3224 };
3225
3226 static const struct join_res join_res_seventh[] =
3227 {
3228     { "malar", "nasalis" },
3229     { "malar", "nasalis" },
3230     { "malar", "nasalis" },
3231 };
3232
3233 static const struct join_res_4col join_res_eighth[] =
3234 {
3235     { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3236     { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3237     { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3238     { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3239     { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3240     { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3241 };
3242
3243 static const struct join_res_uint join_res_ninth[] =
3244 {
3245     { 1, 2, 3, 4, 7, 8 },
3246     { 1, 2, 5, 6, 7, 8 },
3247     { 1, 2, 3, 4, 9, 10 },
3248     { 1, 2, 5, 6, 9, 10 },
3249     { 1, 2, 3, 4, 11, 12 },
3250     { 1, 2, 5, 6, 11, 12 },
3251 };
3252
3253 static void test_join(void)
3254 {
3255     MSIHANDLE hdb, hview, hrec;
3256     LPCSTR query;
3257     CHAR buf[MAX_PATH];
3258     UINT r, count;
3259     DWORD size, i;
3260     BOOL data_correct;
3261
3262     hdb = create_db();
3263     ok( hdb, "failed to create db\n");
3264
3265     r = create_component_table( hdb );
3266     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3267
3268     r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3269     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3270
3271     r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3272     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3273
3274     r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3275     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3276
3277     r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3278     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3279
3280     r = create_feature_components_table( hdb );
3281     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3282
3283     r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3284     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3285
3286     r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3287     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3288
3289     r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3290     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3291
3292     r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3293     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3294
3295     r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3296     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3297
3298     r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3299     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3300
3301     r = create_std_dlls_table( hdb );
3302     ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3303
3304     r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3305     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3306
3307     r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3308     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3309
3310     r = create_binary_table( hdb );
3311     ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3312
3313     r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3314     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3315
3316     r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3317     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3318
3319     r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3320     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3321
3322     query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3323     r = run_query( hdb, 0, query);
3324     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3325
3326     query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3327     r = run_query( hdb, 0, query);
3328     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3329
3330     query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3331     r = run_query( hdb, 0, query);
3332     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3333
3334     query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3335     r = run_query( hdb, 0, query);
3336     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3337
3338     query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3339     r = run_query( hdb, 0, query);
3340     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3341
3342     query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3343     r = run_query( hdb, 0, query);
3344     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3345
3346     query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3347     r = run_query( hdb, 0, query);
3348     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3349
3350     query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3351     r = run_query( hdb, 0, query);
3352     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3353
3354     query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3355     r = run_query( hdb, 0, query);
3356     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3357
3358     query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3359     r = run_query( hdb, 0, query);
3360     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3361
3362     query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3363     r = run_query( hdb, 0, query);
3364     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3365
3366     query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3367     r = run_query( hdb, 0, query);
3368     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3369
3370     query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3371     r = run_query( hdb, 0, query);
3372     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3373
3374     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3375             "FROM `Component`, `FeatureComponents` "
3376             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3377             "ORDER BY `Feature_`";
3378     r = MsiDatabaseOpenView(hdb, query, &hview);
3379     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3380
3381     r = MsiViewExecute(hview, 0);
3382     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3383
3384     i = 0;
3385     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3386     {
3387         count = MsiRecordGetFieldCount( hrec );
3388         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3389
3390         size = MAX_PATH;
3391         r = MsiRecordGetString( hrec, 1, buf, &size );
3392         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3393         ok( !lstrcmp( buf, join_res_first[i].one ),
3394             "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3395
3396         size = MAX_PATH;
3397         r = MsiRecordGetString( hrec, 2, buf, &size );
3398         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3399         ok( !lstrcmp( buf, join_res_first[i].two ),
3400             "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3401
3402         i++;
3403         MsiCloseHandle(hrec);
3404     }
3405
3406     ok( i == 5, "Expected 5 rows, got %d\n", i );
3407     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3408
3409     MsiViewClose(hview);
3410     MsiCloseHandle(hview);
3411
3412     /* try a join without a WHERE condition */
3413     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3414             "FROM `Component`, `FeatureComponents` ";
3415     r = MsiDatabaseOpenView(hdb, query, &hview);
3416     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3417
3418     r = MsiViewExecute(hview, 0);
3419     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3420
3421     i = 0;
3422     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3423     {
3424         i++;
3425         MsiCloseHandle(hrec);
3426     }
3427     ok( i == 24, "Expected 24 rows, got %d\n", i );
3428
3429     MsiViewClose(hview);
3430     MsiCloseHandle(hview);
3431
3432     query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3433             "WHERE FeatureComponents.Component_=Component.Component "
3434             "AND (Feature_='nasalis') ORDER BY Feature_";
3435     r = MsiDatabaseOpenView(hdb, query, &hview);
3436     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3437
3438     r = MsiViewExecute(hview, 0);
3439     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3440
3441     i = 0;
3442     data_correct = TRUE;
3443     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3444     {
3445         count = MsiRecordGetFieldCount( hrec );
3446         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3447
3448         size = MAX_PATH;
3449         r = MsiRecordGetString( hrec, 1, buf, &size );
3450         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3451         if( lstrcmp( buf, join_res_second[i].one ))
3452             data_correct = FALSE;
3453
3454         size = MAX_PATH;
3455         r = MsiRecordGetString( hrec, 2, buf, &size );
3456         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3457         if( lstrcmp( buf, join_res_second[i].two ))
3458             data_correct = FALSE;
3459
3460         i++;
3461         MsiCloseHandle(hrec);
3462     }
3463
3464     ok( data_correct, "data returned in the wrong order\n");
3465
3466     ok( i == 2, "Expected 2 rows, got %d\n", i );
3467     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3468
3469     MsiViewClose(hview);
3470     MsiCloseHandle(hview);
3471
3472     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3473             "FROM `StdDlls`, `Binary` "
3474             "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3475             "ORDER BY `File`";
3476     r = MsiDatabaseOpenView(hdb, query, &hview);
3477     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3478
3479     r = MsiViewExecute(hview, 0);
3480     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3481
3482     i = 0;
3483     data_correct = TRUE;
3484     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3485     {
3486         count = MsiRecordGetFieldCount( hrec );
3487         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3488
3489         size = MAX_PATH;
3490         r = MsiRecordGetString( hrec, 1, buf, &size );
3491         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3492         if( lstrcmp( buf, join_res_third[i].one ) )
3493             data_correct = FALSE;
3494
3495         size = MAX_PATH;
3496         r = MsiRecordGetString( hrec, 2, buf, &size );
3497         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3498         if( lstrcmp( buf, join_res_third[i].two ) )
3499             data_correct = FALSE;
3500
3501         i++;
3502         MsiCloseHandle(hrec);
3503     }
3504     ok( data_correct, "data returned in the wrong order\n");
3505
3506     ok( i == 2, "Expected 2 rows, got %d\n", i );
3507
3508     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3509
3510     MsiViewClose(hview);
3511     MsiCloseHandle(hview);
3512
3513     query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3514             "FROM `StdDlls`, `Binary` "
3515             "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3516             "ORDER BY `Name`";
3517     r = MsiDatabaseOpenView(hdb, query, &hview);
3518     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3519
3520     r = MsiViewExecute(hview, 0);
3521     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3522
3523     i = 0;
3524     data_correct = TRUE;
3525     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3526     {
3527         count = MsiRecordGetFieldCount( hrec );
3528         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3529
3530         size = MAX_PATH;
3531         r = MsiRecordGetString( hrec, 1, buf, &size );
3532         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3533         if( lstrcmp( buf, join_res_fourth[i].one ))
3534             data_correct = FALSE;
3535
3536         size = MAX_PATH;
3537         r = MsiRecordGetString( hrec, 2, buf, &size );
3538         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3539         if( lstrcmp( buf, join_res_fourth[i].two ))
3540             data_correct = FALSE;
3541
3542         i++;
3543         MsiCloseHandle(hrec);
3544     }
3545     ok( data_correct, "data returned in the wrong order\n");
3546
3547     ok( i == 1, "Expected 1 rows, got %d\n", i );
3548     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3549
3550     MsiViewClose(hview);
3551     MsiCloseHandle(hview);
3552
3553     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3554             "FROM `Component`, `FeatureComponents` "
3555             "WHERE `Component`.`Component` = 'zygomatic' "
3556             "AND `FeatureComponents`.`Component_` = 'maxilla' "
3557             "ORDER BY `Feature_`";
3558     r = MsiDatabaseOpenView(hdb, query, &hview);
3559     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3560
3561     r = MsiViewExecute(hview, 0);
3562     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3563
3564     i = 0;
3565     data_correct = TRUE;
3566     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3567     {
3568         count = MsiRecordGetFieldCount( hrec );
3569         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3570
3571         size = MAX_PATH;
3572         r = MsiRecordGetString( hrec, 1, buf, &size );
3573         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3574         if( lstrcmp( buf, join_res_fifth[i].one ))
3575             data_correct = FALSE;
3576
3577         size = MAX_PATH;
3578         r = MsiRecordGetString( hrec, 2, buf, &size );
3579         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3580         if( lstrcmp( buf, join_res_fifth[i].two ))
3581             data_correct = FALSE;
3582
3583         i++;
3584         MsiCloseHandle(hrec);
3585     }
3586     ok( data_correct, "data returned in the wrong order\n");
3587
3588     ok( i == 1, "Expected 1 rows, got %d\n", i );
3589     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3590
3591     MsiViewClose(hview);
3592     MsiCloseHandle(hview);
3593
3594     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3595             "FROM `Component`, `FeatureComponents` "
3596             "WHERE `Component` = 'zygomatic' "
3597             "ORDER BY `Feature_`";
3598     r = MsiDatabaseOpenView(hdb, query, &hview);
3599     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3600
3601     r = MsiViewExecute(hview, 0);
3602     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3603
3604     i = 0;
3605     data_correct = TRUE;
3606     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3607     {
3608         count = MsiRecordGetFieldCount( hrec );
3609         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3610
3611         size = MAX_PATH;
3612         r = MsiRecordGetString( hrec, 1, buf, &size );
3613         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3614         if( lstrcmp( buf, join_res_sixth[i].one ))
3615             data_correct = FALSE;
3616
3617         size = MAX_PATH;
3618         r = MsiRecordGetString( hrec, 2, buf, &size );
3619         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3620         if( lstrcmp( buf, join_res_sixth[i].two ))
3621             data_correct = FALSE;
3622
3623         i++;
3624         MsiCloseHandle(hrec);
3625     }
3626     ok( data_correct, "data returned in the wrong order\n");
3627
3628     ok( i == 6, "Expected 6 rows, got %d\n", i );
3629     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3630
3631     MsiViewClose(hview);
3632     MsiCloseHandle(hview);
3633
3634     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3635             "FROM `Component`, `FeatureComponents` "
3636             "WHERE `Component` = 'zygomatic' "
3637             "AND `Feature_` = 'nasalis' "
3638             "ORDER BY `Feature_`";
3639     r = MsiDatabaseOpenView(hdb, query, &hview);
3640     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3641
3642     r = MsiViewExecute(hview, 0);
3643     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3644
3645     i = 0;
3646     data_correct = TRUE;
3647     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3648     {
3649         count = MsiRecordGetFieldCount( hrec );
3650         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3651
3652         size = MAX_PATH;
3653         r = MsiRecordGetString( hrec, 1, buf, &size );
3654         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3655         if( lstrcmp( buf, join_res_seventh[i].one ))
3656             data_correct = FALSE;
3657
3658         size = MAX_PATH;
3659         r = MsiRecordGetString( hrec, 2, buf, &size );
3660         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3661         if( lstrcmp( buf, join_res_seventh[i].two ))
3662             data_correct = FALSE;
3663
3664         i++;
3665         MsiCloseHandle(hrec);
3666     }
3667
3668     ok( data_correct, "data returned in the wrong order\n");
3669     ok( i == 3, "Expected 3 rows, got %d\n", i );
3670     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3671
3672     MsiViewClose(hview);
3673     MsiCloseHandle(hview);
3674
3675     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3676             "FROM `StdDlls`, `Binary` ";
3677     r = MsiDatabaseOpenView(hdb, query, &hview);
3678     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3679
3680     r = MsiViewExecute(hview, 0);
3681     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3682
3683     i = 0;
3684     data_correct = TRUE;
3685     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3686     {
3687         count = MsiRecordGetFieldCount( hrec );
3688         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3689
3690         size = MAX_PATH;
3691         r = MsiRecordGetString( hrec, 1, buf, &size );
3692         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3693         if( lstrcmp( buf, join_res_eighth[i].one ))
3694             data_correct = FALSE;
3695
3696         size = MAX_PATH;
3697         r = MsiRecordGetString( hrec, 2, buf, &size );
3698         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3699         if( lstrcmp( buf, join_res_eighth[i].four ))
3700             data_correct = FALSE;
3701
3702         i++;
3703         MsiCloseHandle(hrec);
3704     }
3705
3706     ok( data_correct, "data returned in the wrong order\n");
3707     ok( i == 6, "Expected 6 rows, got %d\n", i );
3708     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3709
3710     MsiViewClose(hview);
3711     MsiCloseHandle(hview);
3712
3713     query = "SELECT * FROM `StdDlls`, `Binary` ";
3714     r = MsiDatabaseOpenView(hdb, query, &hview);
3715     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3716
3717     r = MsiViewExecute(hview, 0);
3718     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3719
3720     i = 0;
3721     data_correct = TRUE;
3722     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3723     {
3724         count = MsiRecordGetFieldCount( hrec );
3725         ok( count == 4, "Expected 4 record fields, got %d\n", count );
3726
3727         size = MAX_PATH;
3728         r = MsiRecordGetString( hrec, 1, buf, &size );
3729         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3730         if( lstrcmp( buf, join_res_eighth[i].one ))
3731             data_correct = FALSE;
3732
3733         size = MAX_PATH;
3734         r = MsiRecordGetString( hrec, 2, buf, &size );
3735         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3736         if( lstrcmp( buf, join_res_eighth[i].two ))
3737             data_correct = FALSE;
3738
3739         size = MAX_PATH;
3740         r = MsiRecordGetString( hrec, 3, buf, &size );
3741         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3742         if( lstrcmp( buf, join_res_eighth[i].three ))
3743             data_correct = FALSE;
3744
3745         size = MAX_PATH;
3746         r = MsiRecordGetString( hrec, 4, buf, &size );
3747         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3748         if( lstrcmp( buf, join_res_eighth[i].four ))
3749             data_correct = FALSE;
3750
3751         i++;
3752         MsiCloseHandle(hrec);
3753     }
3754     ok( data_correct, "data returned in the wrong order\n");
3755
3756     ok( i == 6, "Expected 6 rows, got %d\n", i );
3757     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3758
3759     MsiViewClose(hview);
3760     MsiCloseHandle(hview);
3761
3762     query = "SELECT * FROM `One`, `Two`, `Three` ";
3763     r = MsiDatabaseOpenView(hdb, query, &hview);
3764     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3765
3766     r = MsiViewExecute(hview, 0);
3767     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3768
3769     i = 0;
3770     data_correct = TRUE;
3771     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3772     {
3773         count = MsiRecordGetFieldCount( hrec );
3774         ok( count == 6, "Expected 6 record fields, got %d\n", count );
3775
3776         r = MsiRecordGetInteger( hrec, 1 );
3777         if( r != join_res_ninth[i].one )
3778             data_correct = FALSE;
3779
3780         r = MsiRecordGetInteger( hrec, 2 );
3781         if( r != join_res_ninth[i].two )
3782             data_correct = FALSE;
3783
3784         r = MsiRecordGetInteger( hrec, 3 );
3785         if( r != join_res_ninth[i].three )
3786             data_correct = FALSE;
3787
3788         r = MsiRecordGetInteger( hrec, 4 );
3789         if( r != join_res_ninth[i].four )
3790             data_correct = FALSE;
3791
3792         r = MsiRecordGetInteger( hrec, 5 );
3793         if( r != join_res_ninth[i].five )
3794             data_correct = FALSE;
3795
3796         r = MsiRecordGetInteger( hrec, 6);
3797         if( r != join_res_ninth[i].six )
3798             data_correct = FALSE;
3799
3800         i++;
3801         MsiCloseHandle(hrec);
3802     }
3803     ok( data_correct, "data returned in the wrong order\n");
3804
3805     ok( i == 6, "Expected 6 rows, got %d\n", i );
3806     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3807
3808     MsiViewClose(hview);
3809     MsiCloseHandle(hview);
3810
3811     query = "SELECT * FROM `Four`, `Five`";
3812     r = MsiDatabaseOpenView(hdb, query, &hview);
3813     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3814
3815     r = MsiViewExecute(hview, 0);
3816     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3817
3818     r = MsiViewFetch(hview, &hrec);
3819     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3820
3821     MsiViewClose(hview);
3822     MsiCloseHandle(hview);
3823
3824     query = "SELECT * FROM `Nonexistent`, `One`";
3825     r = MsiDatabaseOpenView(hdb, query, &hview);
3826     ok( r == ERROR_BAD_QUERY_SYNTAX,
3827         "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3828
3829     /* try updating a row in a join table */
3830     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3831             "FROM `Component`, `FeatureComponents` "
3832             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3833             "ORDER BY `Feature_`";
3834     r = MsiDatabaseOpenView(hdb, query, &hview);
3835     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3836
3837     r = MsiViewExecute(hview, 0);
3838     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3839
3840     r = MsiViewFetch(hview, &hrec);
3841     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3842
3843     r = MsiRecordSetString( hrec, 1, "epicranius" );
3844     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3845
3846     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3847     ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3848
3849     /* try another valid operation for joins */
3850     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3851     todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3852
3853     /* try an invalid operation for joins */
3854     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3855     ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3856
3857     r = MsiRecordSetString( hrec, 2, "epicranius" );
3858     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3859
3860     /* primary key cannot be updated */
3861     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3862     todo_wine ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3863
3864     MsiCloseHandle(hrec);
3865     MsiViewClose(hview);
3866     MsiCloseHandle(hview);
3867
3868     r = MsiDatabaseOpenView(hdb, query, &hview);
3869     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3870
3871     r = MsiViewExecute(hview, 0);
3872     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3873
3874     r = MsiViewFetch(hview, &hrec);
3875     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3876
3877     size = MAX_PATH;
3878     r = MsiRecordGetString( hrec, 1, buf, &size );
3879     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3880     ok( !lstrcmp( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
3881
3882     MsiCloseHandle(hrec);
3883     MsiViewClose(hview);
3884     MsiCloseHandle(hview);
3885
3886     MsiCloseHandle(hdb);
3887     DeleteFile(msifile);
3888 }
3889
3890 static void test_temporary_table(void)
3891 {
3892     MSICONDITION cond;
3893     MSIHANDLE hdb = 0, view = 0, rec;
3894     const char *query;
3895     UINT r;
3896     char buf[0x10];
3897     DWORD sz;
3898
3899     cond = MsiDatabaseIsTablePersistent(0, NULL);
3900     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3901
3902     hdb = create_db();
3903     ok( hdb, "failed to create db\n");
3904
3905     cond = MsiDatabaseIsTablePersistent(hdb, NULL);
3906     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3907
3908     cond = MsiDatabaseIsTablePersistent(hdb, "_Tables");
3909     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3910
3911     cond = MsiDatabaseIsTablePersistent(hdb, "_Columns");
3912     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3913
3914     cond = MsiDatabaseIsTablePersistent(hdb, "_Storages");
3915     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3916
3917     cond = MsiDatabaseIsTablePersistent(hdb, "_Streams");
3918     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3919
3920     query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
3921     r = run_query(hdb, 0, query);
3922     ok(r == ERROR_SUCCESS, "failed to add table\n");
3923
3924     cond = MsiDatabaseIsTablePersistent(hdb, "P");
3925     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3926
3927     query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
3928     r = run_query(hdb, 0, query);
3929     ok(r == ERROR_SUCCESS, "failed to add table\n");
3930
3931     cond = MsiDatabaseIsTablePersistent(hdb, "P2");
3932     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3933
3934     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
3935     r = run_query(hdb, 0, query);
3936     ok(r == ERROR_SUCCESS, "failed to add table\n");
3937
3938     cond = MsiDatabaseIsTablePersistent(hdb, "T");
3939     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
3940
3941     query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3942     r = run_query(hdb, 0, query);
3943     ok(r == ERROR_SUCCESS, "failed to add table\n");
3944
3945     query = "SELECT * FROM `T2`";
3946     r = MsiDatabaseOpenView(hdb, query, &view);
3947     ok(r == ERROR_BAD_QUERY_SYNTAX,
3948        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3949
3950     cond = MsiDatabaseIsTablePersistent(hdb, "T2");
3951     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3952
3953     query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
3954     r = run_query(hdb, 0, query);
3955     ok(r == ERROR_SUCCESS, "failed to add table\n");
3956
3957     cond = MsiDatabaseIsTablePersistent(hdb, "T3");
3958     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3959
3960     query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3961     r = run_query(hdb, 0, query);
3962     ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
3963
3964     cond = MsiDatabaseIsTablePersistent(hdb, "T4");
3965     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3966
3967     query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
3968     r = run_query(hdb, 0, query);
3969     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
3970
3971     query = "select * from `T`";
3972     r = MsiDatabaseOpenView(hdb, query, &view);
3973     ok(r == ERROR_SUCCESS, "failed to query table\n");
3974     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
3975     ok(r == ERROR_SUCCESS, "failed to get column info\n");
3976
3977     sz = sizeof buf;
3978     r = MsiRecordGetString(rec, 1, buf, &sz);
3979     ok(r == ERROR_SUCCESS, "failed to get string\n");
3980     ok( 0 == strcmp("G255", buf), "wrong column type\n");
3981
3982     sz = sizeof buf;
3983     r = MsiRecordGetString(rec, 2, buf, &sz);
3984     ok(r == ERROR_SUCCESS, "failed to get string\n");
3985     ok( 0 == strcmp("j2", buf), "wrong column type\n");
3986
3987     MsiCloseHandle( rec );
3988     MsiViewClose( view );
3989     MsiCloseHandle( view );
3990
3991     /* query the table data */
3992     rec = 0;
3993     r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
3994     ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
3995     MsiCloseHandle( rec );
3996
3997     /* query the column data */
3998     rec = 0;
3999     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
4000     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4001     if (rec) MsiCloseHandle( rec );
4002
4003     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
4004     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4005     if (rec) MsiCloseHandle( rec );
4006
4007     MsiCloseHandle( hdb );
4008
4009     DeleteFile(msifile);
4010 }
4011
4012 static void test_alter(void)
4013 {
4014     MSICONDITION cond;
4015     MSIHANDLE hdb = 0;
4016     const char *query;
4017     UINT r;
4018
4019     hdb = create_db();
4020     ok( hdb, "failed to create db\n");
4021
4022     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4023     r = run_query(hdb, 0, query);
4024     ok(r == ERROR_SUCCESS, "failed to add table\n");
4025
4026     cond = MsiDatabaseIsTablePersistent(hdb, "T");
4027     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4028
4029     query = "ALTER TABLE `T` HOLD";
4030     r = run_query(hdb, 0, query);
4031     ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4032
4033     query = "ALTER TABLE `T` FREE";
4034     r = run_query(hdb, 0, query);
4035     ok(r == ERROR_SUCCESS, "failed to free table\n");
4036
4037     query = "ALTER TABLE `T` FREE";
4038     r = run_query(hdb, 0, query);
4039     ok(r == ERROR_SUCCESS, "failed to free table\n");
4040
4041     query = "ALTER TABLE `T` FREE";
4042     r = run_query(hdb, 0, query);
4043     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4044
4045     query = "ALTER TABLE `T` HOLD";
4046     r = run_query(hdb, 0, query);
4047     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4048
4049     /* table T is removed */
4050     query = "SELECT * FROM `T`";
4051     r = run_query(hdb, 0, query);
4052     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4053
4054     /* create the table again */
4055     query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4056     r = run_query(hdb, 0, query);
4057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4058
4059     /* up the ref count */
4060     query = "ALTER TABLE `U` HOLD";
4061     r = run_query(hdb, 0, query);
4062     ok(r == ERROR_SUCCESS, "failed to free table\n");
4063
4064     /* add column, no data type */
4065     query = "ALTER TABLE `U` ADD `C`";
4066     r = run_query(hdb, 0, query);
4067     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4068
4069     query = "ALTER TABLE `U` ADD `C` INTEGER";
4070     r = run_query(hdb, 0, query);
4071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4072
4073     /* add column C again */
4074     query = "ALTER TABLE `U` ADD `C` INTEGER";
4075     r = run_query(hdb, 0, query);
4076     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4077
4078     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4079     r = run_query(hdb, 0, query);
4080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4081
4082     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4083     r = run_query(hdb, 0, query);
4084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4085
4086     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4087     r = run_query(hdb, 0, query);
4088     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4089
4090     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4091     r = run_query(hdb, 0, query);
4092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4093
4094     query = "SELECT * FROM `U` WHERE `D` = 8";
4095     r = run_query(hdb, 0, query);
4096     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4097
4098     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4099     r = run_query(hdb, 0, query);
4100     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4101
4102     query = "ALTER COLUMN `D` FREE";
4103     r = run_query(hdb, 0, query);
4104     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4105
4106     /* drop the ref count */
4107     query = "ALTER TABLE `U` FREE";
4108     r = run_query(hdb, 0, query);
4109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4110
4111     /* table is not empty */
4112     query = "SELECT * FROM `U`";
4113     r = run_query(hdb, 0, query);
4114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4115
4116     /* column D is removed */
4117     query = "SELECT * FROM `U` WHERE `D` = 8";
4118     r = run_query(hdb, 0, query);
4119     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4120
4121     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4122     r = run_query(hdb, 0, query);
4123     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4124
4125     /* add the column again */
4126     query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4127     r = run_query(hdb, 0, query);
4128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4129
4130     /* up the ref count */
4131     query = "ALTER TABLE `U` HOLD";
4132     r = run_query(hdb, 0, query);
4133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4134
4135     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4136     r = run_query(hdb, 0, query);
4137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4138
4139     query = "SELECT * FROM `U` WHERE `E` = 16";
4140     r = run_query(hdb, 0, query);
4141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4142
4143     /* drop the ref count */
4144     query = "ALTER TABLE `U` FREE";
4145     r = run_query(hdb, 0, query);
4146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4147
4148     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4149     r = run_query(hdb, 0, query);
4150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4151
4152     query = "SELECT * FROM `U` WHERE `E` = 20";
4153     r = run_query(hdb, 0, query);
4154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4155
4156     /* drop the ref count */
4157     query = "ALTER TABLE `U` FREE";
4158     r = run_query(hdb, 0, query);
4159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4160
4161     /* table still exists */
4162     query = "SELECT * FROM `U`";
4163     r = run_query(hdb, 0, query);
4164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4165
4166     /* col E is removed */
4167     query = "SELECT * FROM `U` WHERE `E` = 20";
4168     r = run_query(hdb, 0, query);
4169     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4170
4171     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4172     r = run_query(hdb, 0, query);
4173     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4174
4175     /* drop the ref count once more */
4176     query = "ALTER TABLE `U` FREE";
4177     r = run_query(hdb, 0, query);
4178     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4179
4180     /* table still exists */
4181     query = "SELECT * FROM `U`";
4182     r = run_query(hdb, 0, query);
4183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4184
4185     MsiCloseHandle( hdb );
4186     DeleteFile(msifile);
4187 }
4188
4189 static void test_integers(void)
4190 {
4191     MSIHANDLE hdb = 0, view = 0, rec = 0;
4192     DWORD count, i;
4193     const char *query;
4194     UINT r;
4195
4196     /* just MsiOpenDatabase should not create a file */
4197     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4198     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4199
4200     /* create a table */
4201     query = "CREATE TABLE `integers` ( "
4202             "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4203             "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4204             "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4205             "PRIMARY KEY `one`)";
4206     r = MsiDatabaseOpenView(hdb, query, &view);
4207     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4208     r = MsiViewExecute(view, 0);
4209     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4210     r = MsiViewClose(view);
4211     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4212     r = MsiCloseHandle(view);
4213     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4214
4215     query = "SELECT * FROM `integers`";
4216     r = MsiDatabaseOpenView(hdb, query, &view);
4217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4218
4219     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
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     count = MsiRecordGetFieldCount(rec);
4234     ok(count == 8, "Expected 8, got %d\n", count);
4235     ok(check_record(rec, 1, "I2"), "Expected I2\n");
4236     ok(check_record(rec, 2, "I2"), "Expected I2\n");
4237     ok(check_record(rec, 3, "I2"), "Expected I2\n");
4238     ok(check_record(rec, 4, "I4"), "Expected I4\n");
4239     ok(check_record(rec, 5, "i2"), "Expected i2\n");
4240     ok(check_record(rec, 6, "i2"), "Expected i2\n");
4241     ok(check_record(rec, 7, "i2"), "Expected i2\n");
4242     ok(check_record(rec, 8, "i4"), "Expected i4\n");
4243     MsiCloseHandle(rec);
4244
4245     MsiViewClose(view);
4246     MsiCloseHandle(view);
4247
4248     /* insert values into it, NULL where NOT NULL is specified */
4249     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4250         "VALUES('', '', '', '', '', '', '', '')";
4251     r = MsiDatabaseOpenView(hdb, query, &view);
4252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4253     r = MsiViewExecute(view, 0);
4254     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4255
4256     MsiViewClose(view);
4257     MsiCloseHandle(view);
4258
4259     query = "SELECT * FROM `integers`";
4260     r = do_query(hdb, query, &rec);
4261     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4262
4263     r = MsiRecordGetFieldCount(rec);
4264     ok(r == -1, "record count wrong: %d\n", r);
4265
4266     MsiCloseHandle(rec);
4267
4268     /* insert legitimate values into it */
4269     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4270         "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4271     r = MsiDatabaseOpenView(hdb, query, &view);
4272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4273     r = MsiViewExecute(view, 0);
4274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4275
4276     query = "SELECT * FROM `integers`";
4277     r = do_query(hdb, query, &rec);
4278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4279
4280     r = MsiRecordGetFieldCount(rec);
4281     ok(r == 8, "record count wrong: %d\n", r);
4282
4283     i = MsiRecordGetInteger(rec, 1);
4284     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4285     i = MsiRecordGetInteger(rec, 3);
4286     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4287     i = MsiRecordGetInteger(rec, 2);
4288     ok(i == 2, "Expected 2, got %d\n", i);
4289     i = MsiRecordGetInteger(rec, 4);
4290     ok(i == 4, "Expected 4, got %d\n", i);
4291     i = MsiRecordGetInteger(rec, 5);
4292     ok(i == 5, "Expected 5, got %d\n", i);
4293     i = MsiRecordGetInteger(rec, 6);
4294     ok(i == 6, "Expected 6, got %d\n", i);
4295     i = MsiRecordGetInteger(rec, 7);
4296     ok(i == 7, "Expected 7, got %d\n", i);
4297     i = MsiRecordGetInteger(rec, 8);
4298     ok(i == 8, "Expected 8, got %d\n", i);
4299
4300     MsiCloseHandle(rec);
4301     MsiViewClose(view);
4302     MsiCloseHandle(view);
4303
4304     r = MsiDatabaseCommit(hdb);
4305     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4306
4307     r = MsiCloseHandle(hdb);
4308     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4309
4310     r = DeleteFile(msifile);
4311     ok(r == TRUE, "file didn't exist after commit\n");
4312 }
4313
4314 static void test_update(void)
4315 {
4316     MSIHANDLE hdb = 0, view = 0, rec = 0;
4317     CHAR result[MAX_PATH];
4318     const char *query;
4319     DWORD size;
4320     UINT r;
4321
4322     /* just MsiOpenDatabase should not create a file */
4323     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4324     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4325
4326     /* create the Control table */
4327     query = "CREATE TABLE `Control` ( "
4328         "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4329         "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4330         "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4331         "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4332     r = MsiDatabaseOpenView(hdb, query, &view);
4333     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4334     r = MsiViewExecute(view, 0);
4335     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4336     r = MsiViewClose(view);
4337     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4338     r = MsiCloseHandle(view);
4339     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4340
4341     /* add a control */
4342     query = "INSERT INTO `Control` ( "
4343         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4344         "`Property`, `Text`, `Control_Next`, `Help` )"
4345         "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4346     r = MsiDatabaseOpenView(hdb, query, &view);
4347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4348     r = MsiViewExecute(view, 0);
4349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4350     r = MsiViewClose(view);
4351     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4352     r = MsiCloseHandle(view);
4353     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4354
4355     /* add a second control */
4356     query = "INSERT INTO `Control` ( "
4357         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4358         "`Property`, `Text`, `Control_Next`, `Help` )"
4359         "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4360     r = MsiDatabaseOpenView(hdb, query, &view);
4361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4362     r = MsiViewExecute(view, 0);
4363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4364     r = MsiViewClose(view);
4365     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4366     r = MsiCloseHandle(view);
4367     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4368
4369     /* add a third control */
4370     query = "INSERT INTO `Control` ( "
4371         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4372         "`Property`, `Text`, `Control_Next`, `Help` )"
4373         "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4374     r = MsiDatabaseOpenView(hdb, query, &view);
4375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4376     r = MsiViewExecute(view, 0);
4377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4378     r = MsiViewClose(view);
4379     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4380     r = MsiCloseHandle(view);
4381     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4382
4383     /* bad table */
4384     query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4385     r = MsiDatabaseOpenView(hdb, query, &view);
4386     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4387
4388     /* bad set column */
4389     query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4390     r = MsiDatabaseOpenView(hdb, query, &view);
4391     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4392
4393     /* bad where condition */
4394     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4395     r = MsiDatabaseOpenView(hdb, query, &view);
4396     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4397
4398     /* just the dialog_ specified */
4399     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4400     r = MsiDatabaseOpenView(hdb, query, &view);
4401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4402     r = MsiViewExecute(view, 0);
4403     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4404     r = MsiViewClose(view);
4405     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4406     r = MsiCloseHandle(view);
4407     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4408
4409     /* check the modified text */
4410     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4411     r = MsiDatabaseOpenView(hdb, query, &view);
4412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4413     r = MsiViewExecute(view, 0);
4414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4415
4416     r = MsiViewFetch(view, &rec);
4417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4418
4419     size = MAX_PATH;
4420     r = MsiRecordGetString(rec, 1, result, &size);
4421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4422     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4423
4424     MsiCloseHandle(rec);
4425
4426     r = MsiViewFetch(view, &rec);
4427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4428
4429     size = MAX_PATH;
4430     r = MsiRecordGetString(rec, 1, result, &size);
4431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4432     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4433
4434     MsiCloseHandle(rec);
4435
4436     r = MsiViewFetch(view, &rec);
4437     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4438
4439     r = MsiViewClose(view);
4440     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4441     r = MsiCloseHandle(view);
4442     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4443
4444     /* dialog_ and control specified */
4445     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4446     r = MsiDatabaseOpenView(hdb, query, &view);
4447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4448     r = MsiViewExecute(view, 0);
4449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4450     r = MsiViewClose(view);
4451     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4452     r = MsiCloseHandle(view);
4453     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4454
4455     /* check the modified text */
4456     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4457     r = MsiDatabaseOpenView(hdb, query, &view);
4458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4459     r = MsiViewExecute(view, 0);
4460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4461
4462     r = MsiViewFetch(view, &rec);
4463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4464
4465     size = MAX_PATH;
4466     r = MsiRecordGetString(rec, 1, result, &size);
4467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4468     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4469
4470     MsiCloseHandle(rec);
4471
4472     r = MsiViewFetch(view, &rec);
4473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4474
4475     size = MAX_PATH;
4476     r = MsiRecordGetString(rec, 1, result, &size);
4477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4478     ok(!lstrlen(result), "Expected an empty string, got %s\n", result);
4479
4480     MsiCloseHandle(rec);
4481
4482     r = MsiViewFetch(view, &rec);
4483     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4484
4485     r = MsiViewClose(view);
4486     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4487     r = MsiCloseHandle(view);
4488     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4489
4490     /* no where condition */
4491     query = "UPDATE `Control` SET `Text` = 'this is text'";
4492     r = MsiDatabaseOpenView(hdb, query, &view);
4493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4494     r = MsiViewExecute(view, 0);
4495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4496     r = MsiViewClose(view);
4497     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4498     r = MsiCloseHandle(view);
4499     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4500
4501     /* check the modified text */
4502     query = "SELECT `Text` FROM `Control`";
4503     r = MsiDatabaseOpenView(hdb, query, &view);
4504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4505     r = MsiViewExecute(view, 0);
4506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4507
4508     r = MsiViewFetch(view, &rec);
4509     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4510
4511     size = MAX_PATH;
4512     r = MsiRecordGetString(rec, 1, result, &size);
4513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4514     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4515
4516     MsiCloseHandle(rec);
4517
4518     r = MsiViewFetch(view, &rec);
4519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4520
4521     size = MAX_PATH;
4522     r = MsiRecordGetString(rec, 1, result, &size);
4523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4524     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4525
4526     MsiCloseHandle(rec);
4527
4528     r = MsiViewFetch(view, &rec);
4529     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4530
4531     size = MAX_PATH;
4532     r = MsiRecordGetString(rec, 1, result, &size);
4533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4534     ok(!lstrcmp(result, "this is text"), "Expected `this is text`, got %s\n", result);
4535
4536     MsiCloseHandle(rec);
4537
4538     r = MsiViewFetch(view, &rec);
4539     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4540
4541     r = MsiViewClose(view);
4542     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4543     r = MsiCloseHandle(view);
4544     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4545
4546     query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4547         "`Orange` CHAR(72),  `Pear` INT PRIMARY KEY `Banana`)";
4548     r = run_query(hdb, 0, query);
4549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4550
4551     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4552         "VALUES('one', 'two', 3)";
4553     r = run_query(hdb, 0, query);
4554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4555
4556     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4557         "VALUES('three', 'four', 5)";
4558     r = run_query(hdb, 0, query);
4559     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4560
4561     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4562         "VALUES('six', 'two', 7)";
4563     r = run_query(hdb, 0, query);
4564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4565
4566     rec = MsiCreateRecord(2);
4567     MsiRecordSetInteger(rec, 1, 8);
4568     MsiRecordSetString(rec, 2, "two");
4569
4570     query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4571     r = run_query(hdb, rec, query);
4572     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4573
4574     MsiCloseHandle(rec);
4575
4576     query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4577     r = MsiDatabaseOpenView(hdb, query, &view);
4578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4579     r = MsiViewExecute(view, 0);
4580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4581
4582     r = MsiViewFetch(view, &rec);
4583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4584
4585     r = MsiRecordGetInteger(rec, 1);
4586     ok(r == 8, "Expected 8, got %d\n", r);
4587
4588     MsiCloseHandle(rec);
4589
4590     r = MsiViewFetch(view, &rec);
4591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4592
4593     r = MsiRecordGetInteger(rec, 1);
4594     ok(r == 8, "Expected 8, got %d\n", r);
4595
4596     MsiCloseHandle(rec);
4597
4598     r = MsiViewFetch(view, &rec);
4599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4600
4601     r = MsiRecordGetInteger(rec, 1);
4602     ok(r == 5, "Expected 5, got %d\n", r);
4603
4604     MsiCloseHandle(rec);
4605
4606     r = MsiViewFetch(view, &rec);
4607     ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4608
4609     MsiViewClose(view);
4610     MsiCloseHandle(view);
4611
4612     r = MsiDatabaseCommit(hdb);
4613     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4614     r = MsiCloseHandle(hdb);
4615     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4616
4617     DeleteFile(msifile);
4618 }
4619
4620 static void test_special_tables(void)
4621 {
4622     const char *query;
4623     MSIHANDLE hdb = 0;
4624     UINT r;
4625
4626     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4627     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4628
4629     query = "CREATE TABLE `_Properties` ( "
4630         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4631     r = run_query(hdb, 0, query);
4632     ok(r == ERROR_SUCCESS, "failed to create table\n");
4633
4634     query = "CREATE TABLE `_Storages` ( "
4635         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4636     r = run_query(hdb, 0, query);
4637     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4638
4639     query = "CREATE TABLE `_Streams` ( "
4640         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4641     r = run_query(hdb, 0, query);
4642     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4643
4644     query = "CREATE TABLE `_Tables` ( "
4645         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4646     r = run_query(hdb, 0, query);
4647     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4648
4649     query = "CREATE TABLE `_Columns` ( "
4650         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4651     r = run_query(hdb, 0, query);
4652     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4653
4654     r = MsiCloseHandle(hdb);
4655     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4656 }
4657
4658 static void test_tables_order(void)
4659 {
4660     const char *query;
4661     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4662     UINT r;
4663     char buffer[100];
4664     DWORD sz;
4665
4666     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4667     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4668
4669     query = "CREATE TABLE `foo` ( "
4670         "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4671     r = run_query(hdb, 0, query);
4672     ok(r == ERROR_SUCCESS, "failed to create table\n");
4673
4674     query = "CREATE TABLE `bar` ( "
4675         "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4676     r = run_query(hdb, 0, query);
4677     ok(r == ERROR_SUCCESS, "failed to create table\n");
4678
4679     query = "CREATE TABLE `baz` ( "
4680         "`bar` INT NOT NULL, "
4681         "`baz` INT NOT NULL, "
4682         "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4683     r = run_query(hdb, 0, query);
4684     ok(r == ERROR_SUCCESS, "failed to create table\n");
4685
4686     /* The names of the tables in the _Tables table must
4687        be in the same order as these names are created in
4688        the strings table. */
4689     query = "SELECT * FROM `_Tables`";
4690     r = MsiDatabaseOpenView(hdb, query, &hview);
4691     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4692     r = MsiViewExecute(hview, 0);
4693     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4694
4695     r = MsiViewFetch(hview, &hrec);
4696     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4697     sz = sizeof(buffer);
4698     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4699     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4700     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4701     r = MsiCloseHandle(hrec);
4702     ok(r == ERROR_SUCCESS, "failed to close record\n");
4703
4704     r = MsiViewFetch(hview, &hrec);
4705     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4706     sz = sizeof(buffer);
4707     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4709     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4710     r = MsiCloseHandle(hrec);
4711     ok(r == ERROR_SUCCESS, "failed to close record\n");
4712
4713     r = MsiViewFetch(hview, &hrec);
4714     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4715     sz = sizeof(buffer);
4716     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4718     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4719     r = MsiCloseHandle(hrec);
4720     ok(r == ERROR_SUCCESS, "failed to close record\n");
4721
4722     r = MsiViewClose(hview);
4723     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4724     r = MsiCloseHandle(hview);
4725     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4726
4727     /* The names of the tables in the _Columns table must
4728        be in the same order as these names are created in
4729        the strings table. */
4730     query = "SELECT * FROM `_Columns`";
4731     r = MsiDatabaseOpenView(hdb, query, &hview);
4732     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4733     r = MsiViewExecute(hview, 0);
4734     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4735
4736     r = MsiViewFetch(hview, &hrec);
4737     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4738     sz = sizeof(buffer);
4739     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4741     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4742     sz = sizeof(buffer);
4743     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4745     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4746     r = MsiCloseHandle(hrec);
4747     ok(r == ERROR_SUCCESS, "failed to close record\n");
4748
4749     r = MsiViewFetch(hview, &hrec);
4750     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4751     sz = sizeof(buffer);
4752     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4754     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4755     sz = sizeof(buffer);
4756     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4758     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4759     r = MsiCloseHandle(hrec);
4760     ok(r == ERROR_SUCCESS, "failed to close record\n");
4761
4762     r = MsiViewFetch(hview, &hrec);
4763     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4764     sz = sizeof(buffer);
4765     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4767     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4768     sz = sizeof(buffer);
4769     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4771     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4772     r = MsiCloseHandle(hrec);
4773     ok(r == ERROR_SUCCESS, "failed to close record\n");
4774
4775     r = MsiViewFetch(hview, &hrec);
4776     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4777     sz = sizeof(buffer);
4778     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4780     ok(!lstrcmp(buffer, "baz"), "Expected baz, got %s\n", buffer);
4781     sz = sizeof(buffer);
4782     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4784     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4785     r = MsiCloseHandle(hrec);
4786     ok(r == ERROR_SUCCESS, "failed to close record\n");
4787
4788     r = MsiViewFetch(hview, &hrec);
4789     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4790     sz = sizeof(buffer);
4791     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4793     ok(!lstrcmp(buffer, "bar"), "Expected bar, got %s\n", buffer);
4794     sz = sizeof(buffer);
4795     r = MsiRecordGetString(hrec, 3, buffer, &sz);
4796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4797     ok(!lstrcmp(buffer, "foo"), "Expected foo, got %s\n", buffer);
4798     r = MsiCloseHandle(hrec);
4799     ok(r == ERROR_SUCCESS, "failed to close record\n");
4800
4801     r = MsiViewClose(hview);
4802     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4803     r = MsiCloseHandle(hview);
4804     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4805
4806     r = MsiCloseHandle(hdb);
4807     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4808
4809     DeleteFile(msifile);
4810 }
4811
4812 static void test_rows_order(void)
4813 {
4814     const char *query;
4815     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4816     UINT r;
4817     char buffer[100];
4818     DWORD sz;
4819
4820     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
4821     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4822
4823     query = "CREATE TABLE `foo` ( "
4824         "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4825     r = run_query(hdb, 0, query);
4826     ok(r == ERROR_SUCCESS, "failed to create table\n");
4827
4828     r = run_query(hdb, 0, "INSERT INTO `foo` "
4829             "( `bar` ) VALUES ( 'A' )");
4830     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4831
4832     r = run_query(hdb, 0, "INSERT INTO `foo` "
4833             "( `bar` ) VALUES ( 'B' )");
4834     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4835
4836     r = run_query(hdb, 0, "INSERT INTO `foo` "
4837             "( `bar` ) VALUES ( 'C' )");
4838     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4839
4840     r = run_query(hdb, 0, "INSERT INTO `foo` "
4841             "( `bar` ) VALUES ( 'D' )");
4842     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4843
4844     r = run_query(hdb, 0, "INSERT INTO `foo` "
4845             "( `bar` ) VALUES ( 'E' )");
4846     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4847
4848     r = run_query(hdb, 0, "INSERT INTO `foo` "
4849             "( `bar` ) VALUES ( 'F' )");
4850     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4851
4852     query = "CREATE TABLE `bar` ( "
4853         "`foo` LONGCHAR NOT NULL, "
4854         "`baz` LONGCHAR NOT NULL "
4855         "PRIMARY KEY `foo` )";
4856     r = run_query(hdb, 0, query);
4857     ok(r == ERROR_SUCCESS, "failed to create table\n");
4858
4859     r = run_query(hdb, 0, "INSERT INTO `bar` "
4860             "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4861     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4862
4863     r = run_query(hdb, 0, "INSERT INTO `bar` "
4864             "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4865     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4866
4867     r = run_query(hdb, 0, "INSERT INTO `bar` "
4868             "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4869     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4870
4871     r = run_query(hdb, 0, "INSERT INTO `bar` "
4872             "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4873     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4874
4875     /* The rows of the table must be ordered by the column values of
4876        each row. For strings, the column value is the string id
4877        in the string table.  */
4878
4879     query = "SELECT * FROM `bar`";
4880     r = MsiDatabaseOpenView(hdb, query, &hview);
4881     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4882     r = MsiViewExecute(hview, 0);
4883     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4884
4885     r = MsiViewFetch(hview, &hrec);
4886     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4887     sz = sizeof(buffer);
4888     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4890     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4891     sz = sizeof(buffer);
4892     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4894     ok(!lstrcmp(buffer, "B"), "Expected B, got %s\n", buffer);
4895     r = MsiCloseHandle(hrec);
4896     ok(r == ERROR_SUCCESS, "failed to close record\n");
4897
4898     r = MsiViewFetch(hview, &hrec);
4899     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4900     sz = sizeof(buffer);
4901     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4903     ok(!lstrcmp(buffer, "C"), "Expected E, got %s\n", buffer);
4904     sz = sizeof(buffer);
4905     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4907     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4908     r = MsiCloseHandle(hrec);
4909     ok(r == ERROR_SUCCESS, "failed to close record\n");
4910
4911     r = MsiViewFetch(hview, &hrec);
4912     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4913     sz = sizeof(buffer);
4914     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4916     ok(!lstrcmp(buffer, "D"), "Expected D, got %s\n", buffer);
4917     sz = sizeof(buffer);
4918     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4920     ok(!lstrcmp(buffer, "E"), "Expected E, got %s\n", buffer);
4921     r = MsiCloseHandle(hrec);
4922     ok(r == ERROR_SUCCESS, "failed to close record\n");
4923
4924     r = MsiViewFetch(hview, &hrec);
4925     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4926     sz = sizeof(buffer);
4927     r = MsiRecordGetString(hrec, 1, buffer, &sz);
4928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4929     ok(!lstrcmp(buffer, "F"), "Expected F, got %s\n", buffer);
4930     sz = sizeof(buffer);
4931     r = MsiRecordGetString(hrec, 2, buffer, &sz);
4932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4933     ok(!lstrcmp(buffer, "A"), "Expected A, got %s\n", buffer);
4934     r = MsiCloseHandle(hrec);
4935     ok(r == ERROR_SUCCESS, "failed to close record\n");
4936
4937     r = MsiViewClose(hview);
4938     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4939     r = MsiCloseHandle(hview);
4940     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4941
4942     r = MsiCloseHandle(hdb);
4943     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4944
4945     DeleteFile(msifile);
4946 }
4947
4948 static void test_collation(void)
4949 {
4950     static const WCHAR query1[] =
4951         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
4952          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
4953          '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
4954     static const WCHAR query2[] =
4955         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
4956          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
4957          '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
4958     static const WCHAR query3[] =
4959         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
4960          '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
4961            ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
4962            'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
4963     static const WCHAR query4[] =
4964         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
4965          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
4966          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
4967     static const WCHAR query5[] =
4968         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
4969          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
4970          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
4971     static const WCHAR query6[] =
4972         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
4973          ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
4974     static const WCHAR letter_C[] = {'C',0};
4975     static const WCHAR letter_D[] = {'D',0};
4976     static const WCHAR letter_a_ring[] = {'a',0x30a,0};
4977     static const WCHAR letter_a_with_ring[] = {0xe5,0};
4978     static const WCHAR letter_a_broken[] = {'a',0xb0,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        broken(!memcmp(bufferW, letter_a_broken, sizeof(letter_a_broken))) /* win9x */,
5059        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
5060     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5061     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5063     ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
5064     MsiCloseHandle(hrec);
5065
5066     r = MsiViewFetch(hview, &hrec);
5067     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5068     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5069     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5071     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5072        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5073     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5074     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5076     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5077     MsiCloseHandle(hrec);
5078
5079     r = MsiViewClose(hview);
5080     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5081     r = MsiCloseHandle(hview);
5082     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5083
5084     r = MsiDatabaseOpenViewW(hdb, query6, &hview);
5085     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5086     r = MsiViewExecute(hview, 0);
5087     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5088
5089     r = MsiViewFetch(hview, &hrec);
5090     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5091     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5092     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5094     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5095        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5096     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5097     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5099     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5100     MsiCloseHandle(hrec);
5101
5102     r = MsiViewFetch(hview, &hrec);
5103     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
5104
5105     r = MsiViewClose(hview);
5106     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5107     r = MsiCloseHandle(hview);
5108     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5109
5110     r = MsiCloseHandle(hdb);
5111     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5112
5113     DeleteFile(msifile);
5114 }
5115
5116 static void test_select_markers(void)
5117 {
5118     MSIHANDLE hdb = 0, rec, view, res;
5119     LPCSTR query;
5120     UINT r;
5121     DWORD size;
5122     CHAR buf[MAX_PATH];
5123
5124     hdb = create_db();
5125     ok( hdb, "failed to create db\n");
5126
5127     r = run_query(hdb, 0,
5128             "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
5129     ok(r == S_OK, "cannot create table: %d\n", r);
5130
5131     r = run_query(hdb, 0, "INSERT INTO `Table` "
5132             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
5133     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5134
5135     r = run_query(hdb, 0, "INSERT INTO `Table` "
5136             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
5137     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5138
5139     r = run_query(hdb, 0, "INSERT INTO `Table` "
5140             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
5141     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5142
5143     r = run_query(hdb, 0, "INSERT INTO `Table` "
5144             "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
5145     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5146
5147     rec = MsiCreateRecord(2);
5148     MsiRecordSetString(rec, 1, "apple");
5149     MsiRecordSetString(rec, 2, "two");
5150
5151     query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
5152     r = MsiDatabaseOpenView(hdb, query, &view);
5153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5154
5155     r = MsiViewExecute(view, rec);
5156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5157
5158     r = MsiViewFetch(view, &res);
5159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5160
5161     size = MAX_PATH;
5162     r = MsiRecordGetString(res, 1, buf, &size);
5163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5164     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5165
5166     size = MAX_PATH;
5167     r = MsiRecordGetString(res, 2, buf, &size);
5168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5169     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5170
5171     r = MsiRecordGetInteger(res, 3);
5172     ok(r == 1, "Expected 1, got %d\n", r);
5173
5174     MsiCloseHandle(res);
5175
5176     r = MsiViewFetch(view, &res);
5177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5178
5179     size = MAX_PATH;
5180     r = MsiRecordGetString(res, 1, buf, &size);
5181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5182     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5183
5184     size = MAX_PATH;
5185     r = MsiRecordGetString(res, 2, buf, &size);
5186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5187     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5188
5189     r = MsiRecordGetInteger(res, 3);
5190     ok(r == 2, "Expected 2, got %d\n", r);
5191
5192     MsiCloseHandle(res);
5193
5194     r = MsiViewFetch(view, &res);
5195     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5196
5197     MsiCloseHandle(rec);
5198     MsiViewClose(view);
5199     MsiCloseHandle(view);
5200
5201     rec = MsiCreateRecord(2);
5202     MsiRecordSetString(rec, 1, "one");
5203     MsiRecordSetInteger(rec, 2, 1);
5204
5205     query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5206     r = MsiDatabaseOpenView(hdb, query, &view);
5207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5208     r = MsiViewExecute(view, rec);
5209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5210
5211     r = MsiViewFetch(view, &res);
5212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5213
5214     size = MAX_PATH;
5215     r = MsiRecordGetString(res, 1, buf, &size);
5216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5217     ok(!lstrcmp(buf, "apple"), "Expected apple, got %s\n", buf);
5218
5219     size = MAX_PATH;
5220     r = MsiRecordGetString(res, 2, buf, &size);
5221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5222     ok(!lstrcmp(buf, "two"), "Expected two, got %s\n", buf);
5223
5224     r = MsiRecordGetInteger(res, 3);
5225     ok(r == 2, "Expected 2, got %d\n", r);
5226
5227     MsiCloseHandle(res);
5228
5229     r = MsiViewFetch(view, &res);
5230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5231
5232     size = MAX_PATH;
5233     r = MsiRecordGetString(res, 1, buf, &size);
5234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5235     ok(!lstrcmp(buf, "banana"), "Expected banana, got %s\n", buf);
5236
5237     size = MAX_PATH;
5238     r = MsiRecordGetString(res, 2, buf, &size);
5239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5240     ok(!lstrcmp(buf, "three"), "Expected three, got %s\n", buf);
5241
5242     r = MsiRecordGetInteger(res, 3);
5243     ok(r == 3, "Expected 3, got %d\n", r);
5244
5245     MsiCloseHandle(res);
5246
5247     r = MsiViewFetch(view, &res);
5248     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5249
5250     MsiCloseHandle(rec);
5251     MsiViewClose(view);
5252     MsiCloseHandle(view);
5253     MsiCloseHandle(hdb);
5254     DeleteFile(msifile);
5255 }
5256
5257 static void test_viewmodify_update(void)
5258 {
5259     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
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     r = MsiCloseHandle( hdb );
5427     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5428 }
5429
5430 static void test_viewmodify_assign(void)
5431 {
5432     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5433     const char *query;
5434     UINT r;
5435
5436     /* setup database */
5437     DeleteFile(msifile);
5438
5439     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5440     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5441
5442     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5443     r = run_query( hdb, 0, query );
5444     ok(r == ERROR_SUCCESS, "query failed\n");
5445
5446     /* assign to view, new primary key */
5447     query = "SELECT * FROM `table`";
5448     r = MsiDatabaseOpenView(hdb, query, &hview);
5449     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5450     r = MsiViewExecute(hview, 0);
5451     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5452
5453     hrec = MsiCreateRecord(2);
5454     ok(hrec != 0, "MsiCreateRecord failed\n");
5455
5456     r = MsiRecordSetInteger(hrec, 1, 1);
5457     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5458     r = MsiRecordSetInteger(hrec, 2, 2);
5459     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5460
5461     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5462     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5463
5464     r = MsiCloseHandle(hrec);
5465     ok(r == ERROR_SUCCESS, "failed to close record\n");
5466
5467     r = MsiViewClose(hview);
5468     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5469     r = MsiCloseHandle(hview);
5470     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5471
5472     query = "SELECT * FROM `table`";
5473     r = MsiDatabaseOpenView(hdb, query, &hview);
5474     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5475     r = MsiViewExecute(hview, 0);
5476     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5477     r = MsiViewFetch(hview, &hrec);
5478     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5479
5480     r = MsiRecordGetInteger(hrec, 1);
5481     ok(r == 1, "Expected 1, got %d\n", r);
5482     r = MsiRecordGetInteger(hrec, 2);
5483     ok(r == 2, "Expected 2, got %d\n", r);
5484
5485     r = MsiCloseHandle(hrec);
5486     ok(r == ERROR_SUCCESS, "failed to close record\n");
5487
5488     r = MsiViewFetch(hview, &hrec);
5489     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5490
5491     r = MsiViewClose(hview);
5492     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5493     r = MsiCloseHandle(hview);
5494     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5495
5496     /* assign to view, primary key matches */
5497     query = "SELECT * FROM `table`";
5498     r = MsiDatabaseOpenView(hdb, query, &hview);
5499     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5500     r = MsiViewExecute(hview, 0);
5501     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5502
5503     hrec = MsiCreateRecord(2);
5504     ok(hrec != 0, "MsiCreateRecord failed\n");
5505
5506     r = MsiRecordSetInteger(hrec, 1, 1);
5507     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5508     r = MsiRecordSetInteger(hrec, 2, 4);
5509     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5510
5511     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5512     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5513
5514     r = MsiCloseHandle(hrec);
5515     ok(r == ERROR_SUCCESS, "failed to close record\n");
5516
5517     r = MsiViewClose(hview);
5518     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5519     r = MsiCloseHandle(hview);
5520     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5521
5522     query = "SELECT * FROM `table`";
5523     r = MsiDatabaseOpenView(hdb, query, &hview);
5524     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5525     r = MsiViewExecute(hview, 0);
5526     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5527     r = MsiViewFetch(hview, &hrec);
5528     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5529
5530     r = MsiRecordGetInteger(hrec, 1);
5531     ok(r == 1, "Expected 1, got %d\n", r);
5532     r = MsiRecordGetInteger(hrec, 2);
5533     ok(r == 4, "Expected 4, got %d\n", r);
5534
5535     r = MsiCloseHandle(hrec);
5536     ok(r == ERROR_SUCCESS, "failed to close record\n");
5537
5538     r = MsiViewFetch(hview, &hrec);
5539     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5540
5541     r = MsiViewClose(hview);
5542     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5543     r = MsiCloseHandle(hview);
5544     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5545
5546     /* close database */
5547     r = MsiCloseHandle( hdb );
5548     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5549 }
5550
5551 static const WCHAR data10[] = { /* MOO */
5552     0x8001, 0x000b,
5553 };
5554 static const WCHAR data11[] = { /* AAR */
5555     0x8002, 0x8005,
5556     0x000c, 0x000f,
5557 };
5558 static const char data12[] = /* _StringData */
5559     "MOOABAARCDonetwofourfive";
5560 static const WCHAR data13[] = { /* _StringPool */
5561 /*  len, refs */
5562     0,   0,    /* string 0 ''     */
5563     0,   0,    /* string 1 ''     */
5564     0,   0,    /* string 2 ''     */
5565     0,   0,    /* string 3 ''     */
5566     0,   0,    /* string 4 ''     */
5567     3,   3,    /* string 5 'MOO'  */
5568     1,   1,    /* string 6 'A'    */
5569     1,   1,    /* string 7 'B'    */
5570     3,   3,    /* string 8 'AAR'  */
5571     1,   1,    /* string 9 'C'    */
5572     1,   1,    /* string a 'D'    */
5573     3,   1,    /* string b 'one'  */
5574     3,   1,    /* string c 'two'  */
5575     0,   0,    /* string d ''     */
5576     4,   1,    /* string e 'four' */
5577     4,   1,    /* string f 'five' */
5578 };
5579
5580 static void test_stringtable(void)
5581 {
5582     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5583     IStorage *stg = NULL;
5584     IStream *stm;
5585     WCHAR name[0x20];
5586     HRESULT hr;
5587     const char *query;
5588     char buffer[MAX_PATH];
5589     WCHAR data[MAX_PATH];
5590     DWORD sz, read;
5591     UINT r;
5592
5593     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5594     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5595     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5596     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5597     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5598
5599     DeleteFile(msifile);
5600
5601     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5603
5604     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5605     r = run_query(hdb, 0, query);
5606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5607
5608     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5609     r = run_query(hdb, 0, query);
5610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5611
5612     /* insert persistent row */
5613     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5614     r = run_query(hdb, 0, query);
5615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5616
5617     /* insert persistent row */
5618     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5619     r = run_query(hdb, 0, query);
5620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5621
5622     /* open a view */
5623     query = "SELECT * FROM `MOO`";
5624     r = MsiDatabaseOpenView(hdb, query, &hview);
5625     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5626     r = MsiViewExecute(hview, 0);
5627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5628
5629     hrec = MsiCreateRecord(2);
5630
5631     r = MsiRecordSetInteger(hrec, 1, 3);
5632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5633     r = MsiRecordSetString(hrec, 2, "three");
5634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5635
5636     /* insert a nonpersistent row */
5637     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5639
5640     r = MsiCloseHandle(hrec);
5641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5642     r = MsiViewClose(hview);
5643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5644     r = MsiCloseHandle(hview);
5645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5646
5647     /* insert persistent row */
5648     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5649     r = run_query(hdb, 0, query);
5650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5651
5652     /* insert persistent row */
5653     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5654     r = run_query(hdb, 0, query);
5655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5656
5657     r = MsiDatabaseCommit(hdb);
5658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5659
5660     r = MsiCloseHandle(hdb);
5661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5662
5663     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
5664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5665
5666     query = "SELECT * FROM `MOO`";
5667     r = MsiDatabaseOpenView(hdb, query, &hview);
5668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5669
5670     r = MsiViewExecute(hview, 0);
5671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5672
5673     r = MsiViewFetch(hview, &hrec);
5674     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5675
5676     r = MsiRecordGetFieldCount(hrec);
5677     ok(r == 2, "Expected 2, got %d\n", r);
5678
5679     r = MsiRecordGetInteger(hrec, 1);
5680     ok(r == 1, "Expected 1, got %d\n", r);
5681
5682     sz = sizeof(buffer);
5683     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5685     ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
5686
5687     r = MsiCloseHandle(hrec);
5688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5689
5690     r = MsiViewFetch(hview, &hrec);
5691     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5692
5693     r = MsiViewClose(hview);
5694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5695     r = MsiCloseHandle(hview);
5696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5697     r = MsiCloseHandle(hrec);
5698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5699
5700     query = "SELECT * FROM `AAR`";
5701     r = MsiDatabaseOpenView(hdb, query, &hview);
5702     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5703
5704     r = MsiViewExecute(hview, 0);
5705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5706
5707     r = MsiViewFetch(hview, &hrec);
5708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5709
5710     r = MsiRecordGetFieldCount(hrec);
5711     ok(r == 2, "Expected 2, got %d\n", r);
5712
5713     r = MsiRecordGetInteger(hrec, 1);
5714     ok(r == 2, "Expected 2, got %d\n", r);
5715
5716     sz = sizeof(buffer);
5717     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5719     ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
5720
5721     r = MsiCloseHandle(hrec);
5722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5723
5724     r = MsiViewFetch(hview, &hrec);
5725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5726
5727     r = MsiRecordGetFieldCount(hrec);
5728     ok(r == 2, "Expected 2, got %d\n", r);
5729
5730     r = MsiRecordGetInteger(hrec, 1);
5731     ok(r == 5, "Expected 5, got %d\n", r);
5732
5733     sz = sizeof(buffer);
5734     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5736     ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
5737
5738     r = MsiCloseHandle(hrec);
5739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5740
5741     r = MsiViewFetch(hview, &hrec);
5742     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5743
5744     r = MsiViewClose(hview);
5745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5746     r = MsiCloseHandle(hview);
5747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5748     r = MsiCloseHandle(hrec);
5749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5750     r = MsiCloseHandle(hdb);
5751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5752
5753     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5754     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5755     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5756     ok(stg != NULL, "Expected non-NULL storage\n");
5757
5758     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5759     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5760     ok(stm != NULL, "Expected non-NULL stream\n");
5761
5762     hr = IStream_Read(stm, data, MAX_PATH, &read);
5763     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5764     ok(read == 4, "Expected 4, got %d\n", read);
5765     todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5766
5767     hr = IStream_Release(stm);
5768     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5769
5770     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5771     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5772     ok(stm != NULL, "Expected non-NULL stream\n");
5773
5774     hr = IStream_Read(stm, data, MAX_PATH, &read);
5775     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5776     ok(read == 8, "Expected 8, got %d\n", read);
5777     todo_wine
5778     {
5779         ok(!memcmp(data, data11, read), "Unexpected data\n");
5780     }
5781
5782     hr = IStream_Release(stm);
5783     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5784
5785     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5786     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5787     ok(stm != NULL, "Expected non-NULL stream\n");
5788
5789     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5790     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5791     ok(read == 24, "Expected 24, got %d\n", read);
5792     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5793
5794     hr = IStream_Release(stm);
5795     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5796
5797     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5798     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5799     ok(stm != NULL, "Expected non-NULL stream\n");
5800
5801     hr = IStream_Read(stm, data, MAX_PATH, &read);
5802     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5803     todo_wine
5804     {
5805         ok(read == 64, "Expected 64, got %d\n", read);
5806         ok(!memcmp(data, data13, read), "Unexpected data\n");
5807     }
5808
5809     hr = IStream_Release(stm);
5810     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5811
5812     hr = IStorage_Release(stg);
5813     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5814
5815     DeleteFileA(msifile);
5816 }
5817
5818 static void test_viewmodify_delete(void)
5819 {
5820     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5821     UINT r;
5822     const char *query;
5823     char buffer[0x100];
5824     DWORD sz;
5825
5826     DeleteFile(msifile);
5827
5828     /* just MsiOpenDatabase should not create a file */
5829     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5831
5832     query = "CREATE TABLE `phone` ( "
5833             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
5834             "PRIMARY KEY `id`)";
5835     r = run_query(hdb, 0, query);
5836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5837
5838     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5839         "VALUES('1', 'Alan', '5030581')";
5840     r = run_query(hdb, 0, query);
5841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5842
5843     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5844         "VALUES('2', 'Barry', '928440')";
5845     r = run_query(hdb, 0, query);
5846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5847
5848     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5849         "VALUES('3', 'Cindy', '2937550')";
5850     r = run_query(hdb, 0, query);
5851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5852
5853     query = "SELECT * FROM `phone` WHERE `id` <= 2";
5854     r = MsiDatabaseOpenView(hdb, query, &hview);
5855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5856     r = MsiViewExecute(hview, 0);
5857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5858     r = MsiViewFetch(hview, &hrec);
5859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5860
5861     /* delete 1 */
5862     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5864
5865     r = MsiCloseHandle(hrec);
5866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5867     r = MsiViewFetch(hview, &hrec);
5868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5869
5870     /* delete 2 */
5871     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5872     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5873
5874     r = MsiCloseHandle(hrec);
5875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5876     r = MsiViewClose(hview);
5877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5878     r = MsiCloseHandle(hview);
5879     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5880
5881     query = "SELECT * FROM `phone`";
5882     r = MsiDatabaseOpenView(hdb, query, &hview);
5883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5884     r = MsiViewExecute(hview, 0);
5885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5886     r = MsiViewFetch(hview, &hrec);
5887     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5888
5889     r = MsiRecordGetInteger(hrec, 1);
5890     ok(r == 3, "Expected 3, got %d\n", r);
5891
5892     sz = sizeof(buffer);
5893     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5894     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5895     ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
5896
5897     sz = sizeof(buffer);
5898     r = MsiRecordGetString(hrec, 3, buffer, &sz);
5899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5900     ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
5901
5902     r = MsiCloseHandle(hrec);
5903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5904
5905     r = MsiViewFetch(hview, &hrec);
5906     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5907
5908     r = MsiViewClose(hview);
5909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5910     r = MsiCloseHandle(hview);
5911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5912     r = MsiCloseHandle(hdb);
5913     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5914 }
5915
5916 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
5917 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
5918 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
5919
5920 static const WCHAR data14[] = { /* _StringPool */
5921 /*  len, refs */
5922     0,   0,    /* string 0 ''    */
5923 };
5924
5925 static const struct {
5926     LPCWSTR name;
5927     const void *data;
5928     DWORD size;
5929 } database_table_data[] =
5930 {
5931     {_Tables, NULL, 0},
5932     {_StringData, NULL, 0},
5933     {_StringPool, data14, sizeof data14},
5934 };
5935
5936 static void enum_stream_names(IStorage *stg)
5937 {
5938     IEnumSTATSTG *stgenum = NULL;
5939     IStream *stm;
5940     HRESULT hr;
5941     STATSTG stat;
5942     ULONG n, count;
5943     BYTE data[MAX_PATH];
5944     BYTE check[MAX_PATH];
5945     DWORD sz;
5946
5947     memset(check, 'a', MAX_PATH);
5948
5949     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
5950     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5951
5952     n = 0;
5953     while(TRUE)
5954     {
5955         count = 0;
5956         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
5957         if(FAILED(hr) || !count)
5958             break;
5959
5960         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
5961            "Expected table %d name to match\n", n);
5962
5963         stm = NULL;
5964         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
5965                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5966         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5967         ok(stm != NULL, "Expected non-NULL stream\n");
5968
5969         CoTaskMemFree(stat.pwcsName);
5970
5971         sz = MAX_PATH;
5972         memset(data, 'a', MAX_PATH);
5973         hr = IStream_Read(stm, data, sz, &count);
5974         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
5975
5976         ok(count == database_table_data[n].size,
5977            "Expected %d, got %d\n", database_table_data[n].size, count);
5978
5979         if (!database_table_data[n].size)
5980             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
5981         else
5982             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
5983                "Expected table %d data to match\n", n);
5984
5985         IStream_Release(stm);
5986         n++;
5987     }
5988
5989     ok(n == 3, "Expected 3, got %d\n", n);
5990
5991     IEnumSTATSTG_Release(stgenum);
5992 }
5993
5994 static void test_defaultdatabase(void)
5995 {
5996     UINT r;
5997     HRESULT hr;
5998     MSIHANDLE hdb;
5999     IStorage *stg = NULL;
6000
6001     DeleteFile(msifile);
6002
6003     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6005
6006     r = MsiDatabaseCommit(hdb);
6007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6008
6009     MsiCloseHandle(hdb);
6010
6011     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6012     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6013     ok(stg != NULL, "Expected non-NULL stg\n");
6014
6015     enum_stream_names(stg);
6016
6017     IStorage_Release(stg);
6018     DeleteFileA(msifile);
6019 }
6020
6021 static void test_order(void)
6022 {
6023     MSIHANDLE hdb, hview, hrec;
6024     CHAR buffer[MAX_PATH];
6025     LPCSTR query;
6026     UINT r, sz;
6027     int val;
6028
6029     hdb = create_db();
6030     ok(hdb, "failed to create db\n");
6031
6032     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6033     r = run_query(hdb, 0, query);
6034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6035
6036     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6037     r = run_query(hdb, 0, query);
6038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6039
6040     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6041     r = run_query(hdb, 0, query);
6042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6043
6044     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6045     r = run_query(hdb, 0, query);
6046     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6047
6048     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6049     r = run_query(hdb, 0, query);
6050     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6051
6052     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6053     r = run_query(hdb, 0, query);
6054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6055
6056     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6057     r = run_query(hdb, 0, query);
6058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6059
6060     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6061     r = run_query(hdb, 0, query);
6062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6063
6064     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6065     r = run_query(hdb, 0, query);
6066     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6067
6068     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6069     r = MsiDatabaseOpenView(hdb, query, &hview);
6070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6071     r = MsiViewExecute(hview, 0);
6072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6073
6074     r = MsiViewFetch(hview, &hrec);
6075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6076
6077     val = MsiRecordGetInteger(hrec, 1);
6078     ok(val == 3, "Expected 3, got %d\n", val);
6079
6080     val = MsiRecordGetInteger(hrec, 2);
6081     ok(val == 4, "Expected 3, got %d\n", val);
6082
6083     MsiCloseHandle(hrec);
6084
6085     r = MsiViewFetch(hview, &hrec);
6086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6087
6088     val = MsiRecordGetInteger(hrec, 1);
6089     ok(val == 5, "Expected 5, got %d\n", val);
6090
6091     val = MsiRecordGetInteger(hrec, 2);
6092     ok(val == 6, "Expected 6, got %d\n", val);
6093
6094     MsiCloseHandle(hrec);
6095
6096     r = MsiViewFetch(hview, &hrec);
6097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6098
6099     val = MsiRecordGetInteger(hrec, 1);
6100     ok(val == 1, "Expected 1, got %d\n", val);
6101
6102     val = MsiRecordGetInteger(hrec, 2);
6103     ok(val == 2, "Expected 2, got %d\n", val);
6104
6105     MsiCloseHandle(hrec);
6106
6107     r = MsiViewFetch(hview, &hrec);
6108     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6109
6110     MsiViewClose(hview);
6111     MsiCloseHandle(hview);
6112
6113     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6114     r = MsiDatabaseOpenView(hdb, query, &hview);
6115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6116     r = MsiViewExecute(hview, 0);
6117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6118
6119     r = MsiViewFetch(hview, &hrec);
6120     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6121
6122     val = MsiRecordGetInteger(hrec, 1);
6123     ok(val == 1, "Expected 1, got %d\n", val);
6124
6125     val = MsiRecordGetInteger(hrec, 2);
6126     ok(val == 12, "Expected 12, got %d\n", val);
6127
6128     MsiCloseHandle(hrec);
6129
6130     r = MsiViewFetch(hview, &hrec);
6131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6132
6133     val = MsiRecordGetInteger(hrec, 1);
6134     ok(val == 3, "Expected 3, got %d\n", val);
6135
6136     val = MsiRecordGetInteger(hrec, 2);
6137     ok(val == 12, "Expected 12, got %d\n", val);
6138
6139     MsiCloseHandle(hrec);
6140
6141     r = MsiViewFetch(hview, &hrec);
6142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6143
6144     val = MsiRecordGetInteger(hrec, 1);
6145     ok(val == 5, "Expected 5, got %d\n", val);
6146
6147     val = MsiRecordGetInteger(hrec, 2);
6148     ok(val == 12, "Expected 12, got %d\n", val);
6149
6150     MsiCloseHandle(hrec);
6151
6152     r = MsiViewFetch(hview, &hrec);
6153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6154
6155     val = MsiRecordGetInteger(hrec, 1);
6156     ok(val == 1, "Expected 1, got %d\n", val);
6157
6158     val = MsiRecordGetInteger(hrec, 2);
6159     ok(val == 14, "Expected 14, got %d\n", val);
6160
6161     MsiCloseHandle(hrec);
6162
6163     r = MsiViewFetch(hview, &hrec);
6164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6165
6166     val = MsiRecordGetInteger(hrec, 1);
6167     ok(val == 3, "Expected 3, got %d\n", val);
6168
6169     val = MsiRecordGetInteger(hrec, 2);
6170     ok(val == 14, "Expected 14, got %d\n", val);
6171
6172     MsiCloseHandle(hrec);
6173
6174     r = MsiViewFetch(hview, &hrec);
6175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6176
6177     val = MsiRecordGetInteger(hrec, 1);
6178     ok(val == 5, "Expected 5, got %d\n", val);
6179
6180     val = MsiRecordGetInteger(hrec, 2);
6181     ok(val == 14, "Expected 14, got %d\n", val);
6182
6183     MsiCloseHandle(hrec);
6184
6185     r = MsiViewFetch(hview, &hrec);
6186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6187
6188     val = MsiRecordGetInteger(hrec, 1);
6189     ok(val == 1, "Expected 1, got %d\n", val);
6190
6191     val = MsiRecordGetInteger(hrec, 2);
6192     ok(val == 10, "Expected 10, got %d\n", val);
6193
6194     MsiCloseHandle(hrec);
6195
6196     r = MsiViewFetch(hview, &hrec);
6197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6198
6199     val = MsiRecordGetInteger(hrec, 1);
6200     ok(val == 3, "Expected 3, got %d\n", val);
6201
6202     val = MsiRecordGetInteger(hrec, 2);
6203     ok(val == 10, "Expected 10, got %d\n", val);
6204
6205     MsiCloseHandle(hrec);
6206
6207     r = MsiViewFetch(hview, &hrec);
6208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6209
6210     val = MsiRecordGetInteger(hrec, 1);
6211     ok(val == 5, "Expected 5, got %d\n", val);
6212
6213     val = MsiRecordGetInteger(hrec, 2);
6214     ok(val == 10, "Expected 10, got %d\n", val);
6215
6216     MsiCloseHandle(hrec);
6217
6218     r = MsiViewFetch(hview, &hrec);
6219     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6220
6221     MsiViewClose(hview);
6222     MsiCloseHandle(hview);
6223
6224     query = "SELECT * FROM `Empty` ORDER BY `A`";
6225     r = MsiDatabaseOpenView(hdb, query, &hview);
6226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6227     r = MsiViewExecute(hview, 0);
6228     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6229
6230     r = MsiViewFetch(hview, &hrec);
6231     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6232
6233     MsiViewClose(hview);
6234     MsiCloseHandle(hview);
6235
6236     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6237     r = run_query(hdb, 0, query);
6238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6239
6240     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6241     r = run_query(hdb, 0, query);
6242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6243
6244     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6245     r = run_query(hdb, 0, query);
6246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6247
6248     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6249     r = run_query(hdb, 0, query);
6250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6251
6252     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6253     r = MsiDatabaseOpenView(hdb, query, &hview);
6254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6255     r = MsiViewExecute(hview, 0);
6256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6257
6258     r = MsiViewFetch(hview, &hrec);
6259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6260
6261     sz = sizeof(buffer);
6262     r = MsiRecordGetString(hrec, 1, buffer, &sz);
6263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6264     ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6265
6266     r = MsiRecordGetInteger(hrec, 2);
6267     ok(r == 3, "Expected 3, got %d\n", r);
6268
6269     MsiCloseHandle(hrec);
6270
6271     r = MsiViewFetch(hview, &hrec);
6272     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6273
6274     MsiViewClose(hview);
6275     MsiCloseHandle(hview);
6276     MsiCloseHandle(hdb);
6277 }
6278
6279 static void test_viewmodify_delete_temporary(void)
6280 {
6281     MSIHANDLE hdb, hview, hrec;
6282     const char *query;
6283     UINT r;
6284
6285     DeleteFile(msifile);
6286
6287     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6289
6290     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6291     r = run_query(hdb, 0, query);
6292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6293
6294     query = "SELECT * FROM `Table`";
6295     r = MsiDatabaseOpenView(hdb, query, &hview);
6296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6297     r = MsiViewExecute(hview, 0);
6298     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6299
6300     hrec = MsiCreateRecord(1);
6301     MsiRecordSetInteger(hrec, 1, 1);
6302
6303     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6305
6306     MsiCloseHandle(hrec);
6307
6308     hrec = MsiCreateRecord(1);
6309     MsiRecordSetInteger(hrec, 1, 2);
6310
6311     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6313
6314     MsiCloseHandle(hrec);
6315
6316     hrec = MsiCreateRecord(1);
6317     MsiRecordSetInteger(hrec, 1, 3);
6318
6319     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6321
6322     MsiCloseHandle(hrec);
6323
6324     hrec = MsiCreateRecord(1);
6325     MsiRecordSetInteger(hrec, 1, 4);
6326
6327     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6329
6330     MsiCloseHandle(hrec);
6331     MsiViewClose(hview);
6332     MsiCloseHandle(hview);
6333
6334     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6335     r = MsiDatabaseOpenView(hdb, query, &hview);
6336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6337     r = MsiViewExecute(hview, 0);
6338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6339     r = MsiViewFetch(hview, &hrec);
6340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6341
6342     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6344
6345     MsiCloseHandle(hrec);
6346     MsiViewClose(hview);
6347     MsiCloseHandle(hview);
6348
6349     query = "SELECT * FROM `Table` WHERE  `A` = 3";
6350     r = MsiDatabaseOpenView(hdb, query, &hview);
6351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6352     r = MsiViewExecute(hview, 0);
6353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6354     r = MsiViewFetch(hview, &hrec);
6355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6356
6357     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6359
6360     MsiCloseHandle(hrec);
6361     MsiViewClose(hview);
6362     MsiCloseHandle(hview);
6363
6364     query = "SELECT * FROM `Table` ORDER BY `A`";
6365     r = MsiDatabaseOpenView(hdb, query, &hview);
6366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6367     r = MsiViewExecute(hview, 0);
6368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6369
6370     r = MsiViewFetch(hview, &hrec);
6371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6372
6373     r = MsiRecordGetInteger(hrec, 1);
6374     ok(r == 1, "Expected 1, got %d\n", r);
6375
6376     MsiCloseHandle(hrec);
6377
6378     r = MsiViewFetch(hview, &hrec);
6379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6380
6381     r = MsiRecordGetInteger(hrec, 1);
6382     ok(r == 4, "Expected 4, got %d\n", r);
6383
6384     MsiCloseHandle(hrec);
6385
6386     r = MsiViewFetch(hview, &hrec);
6387     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6388
6389     MsiViewClose(hview);
6390     MsiCloseHandle(hview);
6391     MsiCloseHandle(hdb);
6392     DeleteFileA(msifile);
6393 }
6394
6395 static void test_deleterow(void)
6396 {
6397     MSIHANDLE hdb, hview, hrec;
6398     const char *query;
6399     char buf[MAX_PATH];
6400     UINT r;
6401     DWORD size;
6402
6403     DeleteFile(msifile);
6404
6405     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407
6408     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6409     r = run_query(hdb, 0, query);
6410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6411
6412     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6413     r = run_query(hdb, 0, query);
6414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6415
6416     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6417     r = run_query(hdb, 0, query);
6418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6419
6420     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6421     r = run_query(hdb, 0, query);
6422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6423
6424     r = MsiDatabaseCommit(hdb);
6425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6426
6427     MsiCloseHandle(hdb);
6428
6429     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
6430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6431
6432     query = "SELECT * FROM `Table`";
6433     r = MsiDatabaseOpenView(hdb, query, &hview);
6434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6435     r = MsiViewExecute(hview, 0);
6436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6437
6438     r = MsiViewFetch(hview, &hrec);
6439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6440
6441     size = MAX_PATH;
6442     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6444     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6445
6446     MsiCloseHandle(hrec);
6447
6448     r = MsiViewFetch(hview, &hrec);
6449     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6450
6451     MsiViewClose(hview);
6452     MsiCloseHandle(hview);
6453     MsiCloseHandle(hdb);
6454     DeleteFileA(msifile);
6455 }
6456
6457 static const CHAR import_dat[] = "A\n"
6458                                  "s72\n"
6459                                  "Table\tA\n"
6460                                  "This is a new 'string' ok\n";
6461
6462 static void test_quotes(void)
6463 {
6464     MSIHANDLE hdb, hview, hrec;
6465     const char *query;
6466     char buf[MAX_PATH];
6467     UINT r;
6468     DWORD size;
6469
6470     DeleteFile(msifile);
6471
6472     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6474
6475     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6476     r = run_query(hdb, 0, query);
6477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6478
6479     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6480     r = run_query(hdb, 0, query);
6481     ok(r == ERROR_BAD_QUERY_SYNTAX,
6482        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6483
6484     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6485     r = run_query(hdb, 0, query);
6486     ok(r == ERROR_BAD_QUERY_SYNTAX,
6487        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6488
6489     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6490     r = run_query(hdb, 0, query);
6491     ok(r == ERROR_BAD_QUERY_SYNTAX,
6492        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6493
6494     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6495     r = run_query(hdb, 0, query);
6496     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6497
6498     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6499     r = run_query(hdb, 0, query);
6500     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6501
6502     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6503     r = run_query(hdb, 0, query);
6504     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6505
6506     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6507     r = run_query(hdb, 0, query);
6508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6509
6510     query = "SELECT * FROM `Table`";
6511     r = MsiDatabaseOpenView(hdb, query, &hview);
6512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6513
6514     r = MsiViewExecute(hview, 0);
6515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6516
6517     r = MsiViewFetch(hview, &hrec);
6518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6519
6520     size = MAX_PATH;
6521     r = MsiRecordGetString(hrec, 1, buf, &size);
6522     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6523     ok(!lstrcmp(buf, "This is a \"string\" ok"),
6524        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6525
6526     MsiCloseHandle(hrec);
6527
6528     r = MsiViewFetch(hview, &hrec);
6529     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6530
6531     MsiViewClose(hview);
6532     MsiCloseHandle(hview);
6533
6534     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6535
6536     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6538
6539     DeleteFileA("import.idt");
6540
6541     query = "SELECT * FROM `Table`";
6542     r = MsiDatabaseOpenView(hdb, query, &hview);
6543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6544
6545     r = MsiViewExecute(hview, 0);
6546     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6547
6548     r = MsiViewFetch(hview, &hrec);
6549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6550
6551     size = MAX_PATH;
6552     r = MsiRecordGetString(hrec, 1, buf, &size);
6553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6554     ok(!lstrcmp(buf, "This is a new 'string' ok"),
6555        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6556
6557     MsiCloseHandle(hrec);
6558
6559     r = MsiViewFetch(hview, &hrec);
6560     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6561
6562     MsiViewClose(hview);
6563     MsiCloseHandle(hview);
6564     MsiCloseHandle(hdb);
6565     DeleteFileA(msifile);
6566 }
6567
6568 static void test_carriagereturn(void)
6569 {
6570     MSIHANDLE hdb, hview, hrec;
6571     const char *query;
6572     char buf[MAX_PATH];
6573     UINT r;
6574     DWORD size;
6575
6576     DeleteFile(msifile);
6577
6578     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6579     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6580
6581     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6582     r = run_query(hdb, 0, query);
6583     ok(r == ERROR_BAD_QUERY_SYNTAX,
6584        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6585
6586     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6587     r = run_query(hdb, 0, query);
6588     ok(r == ERROR_BAD_QUERY_SYNTAX,
6589        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6590
6591     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6592     r = run_query(hdb, 0, query);
6593     ok(r == ERROR_BAD_QUERY_SYNTAX,
6594        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6595
6596     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6597     r = run_query(hdb, 0, query);
6598     ok(r == ERROR_BAD_QUERY_SYNTAX,
6599        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6600
6601     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6602     r = run_query(hdb, 0, query);
6603     ok(r == ERROR_BAD_QUERY_SYNTAX,
6604        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6605
6606     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6607     r = run_query(hdb, 0, query);
6608     ok(r == ERROR_BAD_QUERY_SYNTAX,
6609        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6610
6611     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6612     r = run_query(hdb, 0, query);
6613     ok(r == ERROR_BAD_QUERY_SYNTAX,
6614        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6615
6616     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6617     r = run_query(hdb, 0, query);
6618     ok(r == ERROR_BAD_QUERY_SYNTAX,
6619        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6620
6621     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6622     r = run_query(hdb, 0, query);
6623     ok(r == ERROR_BAD_QUERY_SYNTAX,
6624        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6625
6626     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6627     r = run_query(hdb, 0, query);
6628     ok(r == ERROR_BAD_QUERY_SYNTAX,
6629        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6630
6631     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6632     r = run_query(hdb, 0, query);
6633     ok(r == ERROR_BAD_QUERY_SYNTAX,
6634        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6635
6636     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6637     r = run_query(hdb, 0, query);
6638     ok(r == ERROR_BAD_QUERY_SYNTAX,
6639        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6640
6641     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6642     r = run_query(hdb, 0, query);
6643     ok(r == ERROR_BAD_QUERY_SYNTAX,
6644        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6645
6646     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6647     r = run_query(hdb, 0, query);
6648     ok(r == ERROR_BAD_QUERY_SYNTAX,
6649        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6650
6651     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6652     r = run_query(hdb, 0, query);
6653     ok(r == ERROR_BAD_QUERY_SYNTAX,
6654        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6655
6656     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6657     r = run_query(hdb, 0, query);
6658     ok(r == ERROR_BAD_QUERY_SYNTAX,
6659        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6660
6661     query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6662     r = run_query(hdb, 0, query);
6663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6664
6665     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6666     r = run_query(hdb, 0, query);
6667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6668
6669     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6670     r = run_query(hdb, 0, query);
6671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6672
6673     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6674     r = run_query(hdb, 0, query);
6675     ok(r == ERROR_BAD_QUERY_SYNTAX,
6676        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6677
6678     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6679     r = run_query(hdb, 0, query);
6680     ok(r == ERROR_BAD_QUERY_SYNTAX,
6681        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6682
6683     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6684     r = run_query(hdb, 0, query);
6685     ok(r == ERROR_BAD_QUERY_SYNTAX,
6686        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6687
6688     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6689     r = run_query(hdb, 0, query);
6690     ok(r == ERROR_BAD_QUERY_SYNTAX,
6691        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6692
6693     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6694     r = run_query(hdb, 0, query);
6695     ok(r == ERROR_BAD_QUERY_SYNTAX,
6696        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6697
6698     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6699     r = run_query(hdb, 0, query);
6700     ok(r == ERROR_BAD_QUERY_SYNTAX,
6701        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6702
6703     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6704     r = run_query(hdb, 0, query);
6705     ok(r == ERROR_BAD_QUERY_SYNTAX,
6706        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6707
6708     query = "SELECT * FROM `_Tables`";
6709     r = MsiDatabaseOpenView(hdb, query, &hview);
6710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6711     r = MsiViewExecute(hview, 0);
6712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6713
6714     r = MsiViewFetch(hview, &hrec);
6715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6716
6717     size = MAX_PATH;
6718     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6720     ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6721
6722     MsiCloseHandle(hrec);
6723
6724     r = MsiViewFetch(hview, &hrec);
6725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6726
6727     size = MAX_PATH;
6728     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6730     ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6731
6732     MsiCloseHandle(hrec);
6733
6734     r = MsiViewFetch(hview, &hrec);
6735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6736
6737     size = MAX_PATH;
6738     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6740     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6741
6742     MsiCloseHandle(hrec);
6743
6744     r = MsiViewFetch(hview, &hrec);
6745     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6746
6747     MsiViewClose(hview);
6748     MsiCloseHandle(hview);
6749
6750     MsiCloseHandle(hdb);
6751     DeleteFileA(msifile);
6752 }
6753
6754 static void test_noquotes(void)
6755 {
6756     MSIHANDLE hdb, hview, hrec;
6757     const char *query;
6758     char buf[MAX_PATH];
6759     UINT r;
6760     DWORD size;
6761
6762     DeleteFile(msifile);
6763
6764     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6766
6767     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6768     r = run_query(hdb, 0, query);
6769     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6770
6771     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6772     r = run_query(hdb, 0, query);
6773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6774
6775     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6776     r = run_query(hdb, 0, query);
6777     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6778
6779     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6780     r = run_query(hdb, 0, query);
6781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6782
6783     query = "SELECT * FROM `_Tables`";
6784     r = MsiDatabaseOpenView(hdb, query, &hview);
6785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6786     r = MsiViewExecute(hview, 0);
6787     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6788
6789     r = MsiViewFetch(hview, &hrec);
6790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6791
6792     size = MAX_PATH;
6793     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6795     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6796
6797     MsiCloseHandle(hrec);
6798
6799     r = MsiViewFetch(hview, &hrec);
6800     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6801
6802     size = MAX_PATH;
6803     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6805     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6806
6807     MsiCloseHandle(hrec);
6808
6809     r = MsiViewFetch(hview, &hrec);
6810     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6811
6812     size = MAX_PATH;
6813     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6815     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6816
6817     MsiCloseHandle(hrec);
6818
6819     r = MsiViewFetch(hview, &hrec);
6820     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6821
6822     MsiViewClose(hview);
6823     MsiCloseHandle(hview);
6824
6825     query = "SELECT * FROM `_Columns`";
6826     r = MsiDatabaseOpenView(hdb, query, &hview);
6827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6828     r = MsiViewExecute(hview, 0);
6829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6830
6831     r = MsiViewFetch(hview, &hrec);
6832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6833
6834     size = MAX_PATH;
6835     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6837     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6838
6839     r = MsiRecordGetInteger(hrec, 2);
6840     ok(r == 1, "Expected 1, got %d\n", r);
6841
6842     size = MAX_PATH;
6843     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6845     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6846
6847     MsiCloseHandle(hrec);
6848
6849     r = MsiViewFetch(hview, &hrec);
6850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6851
6852     size = MAX_PATH;
6853     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6855     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6856
6857     r = MsiRecordGetInteger(hrec, 2);
6858     ok(r == 1, "Expected 1, got %d\n", r);
6859
6860     size = MAX_PATH;
6861     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6862     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6863     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6864
6865     MsiCloseHandle(hrec);
6866
6867     r = MsiViewFetch(hview, &hrec);
6868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6869
6870     size = MAX_PATH;
6871     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6872     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6873     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6874
6875     r = MsiRecordGetInteger(hrec, 2);
6876     ok(r == 1, "Expected 1, got %d\n", r);
6877
6878     size = MAX_PATH;
6879     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6881     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6882
6883     MsiCloseHandle(hrec);
6884
6885     r = MsiViewFetch(hview, &hrec);
6886     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6887
6888     MsiViewClose(hview);
6889     MsiCloseHandle(hview);
6890
6891     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
6892     r = run_query(hdb, 0, query);
6893     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6894
6895     query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
6896     r = run_query(hdb, 0, query);
6897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6898
6899     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
6900     r = run_query(hdb, 0, query);
6901     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6902
6903     query = "SELECT * FROM Table WHERE `A` = 'hi'";
6904     r = run_query(hdb, 0, query);
6905     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6906
6907     query = "SELECT * FROM `Table` WHERE `A` = hi";
6908     r = run_query(hdb, 0, query);
6909     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6910
6911     query = "SELECT * FROM Table";
6912     r = run_query(hdb, 0, query);
6913     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6914
6915     query = "SELECT * FROM Table2";
6916     r = MsiDatabaseOpenView(hdb, query, &hview);
6917     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6918     r = MsiViewExecute(hview, 0);
6919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6920
6921     r = MsiViewFetch(hview, &hrec);
6922     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6923
6924     MsiViewClose(hview);
6925     MsiCloseHandle(hview);
6926
6927     query = "SELECT * FROM `Table` WHERE A = 'hi'";
6928     r = MsiDatabaseOpenView(hdb, query, &hview);
6929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6930     r = MsiViewExecute(hview, 0);
6931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
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, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
6940
6941     MsiCloseHandle(hrec);
6942
6943     r = MsiViewFetch(hview, &hrec);
6944     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6945
6946     MsiViewClose(hview);
6947     MsiCloseHandle(hview);
6948     MsiCloseHandle(hdb);
6949     DeleteFileA(msifile);
6950 }
6951
6952 static void read_file_data(LPCSTR filename, LPSTR buffer)
6953 {
6954     HANDLE file;
6955     DWORD read;
6956
6957     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
6958     ZeroMemory(buffer, MAX_PATH);
6959     ReadFile(file, buffer, MAX_PATH, &read, NULL);
6960     CloseHandle(file);
6961 }
6962
6963 static void test_forcecodepage(void)
6964 {
6965     MSIHANDLE hdb;
6966     const char *query;
6967     char buffer[MAX_PATH];
6968     UINT r;
6969
6970     DeleteFile(msifile);
6971
6972     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6974
6975     query = "SELECT * FROM `_ForceCodepage`";
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 = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6980     r = run_query(hdb, 0, query);
6981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6982
6983     query = "SELECT * FROM `_ForceCodepage`";
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     r = MsiDatabaseCommit(hdb);
6988     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6989
6990     query = "SELECT * FROM `_ForceCodepage`";
6991     r = run_query(hdb, 0, query);
6992     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6993
6994     MsiCloseHandle(hdb);
6995
6996     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb);
6997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6998
6999     query = "SELECT * FROM `_ForceCodepage`";
7000     r = run_query(hdb, 0, query);
7001     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7002
7003     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7005
7006     read_file_data("forcecodepage.idt", buffer);
7007     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7008        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"", buffer);
7009
7010     MsiCloseHandle(hdb);
7011     DeleteFileA(msifile);
7012     DeleteFileA("forcecodepage.idt");
7013 }
7014
7015 static void test_viewmodify_refresh(void)
7016 {
7017     MSIHANDLE hdb, hview, hrec;
7018     const char *query;
7019     char buffer[MAX_PATH];
7020     UINT r;
7021     DWORD size;
7022
7023     DeleteFile(msifile);
7024
7025     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7027
7028     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7029     r = run_query(hdb, 0, query);
7030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7031
7032     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7033     r = run_query(hdb, 0, query);
7034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7035
7036     query = "SELECT * FROM `Table`";
7037     r = MsiDatabaseOpenView(hdb, query, &hview);
7038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7039     r = MsiViewExecute(hview, 0);
7040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7041
7042     r = MsiViewFetch(hview, &hrec);
7043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7044
7045     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7046     r = run_query(hdb, 0, query);
7047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7048
7049     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7050     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7051
7052     size = MAX_PATH;
7053     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7055     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7056     ok(size == 2, "Expected 2, got %d\n", size);
7057
7058     r = MsiRecordGetInteger(hrec, 2);
7059     ok(r == 2, "Expected 2, got %d\n", r);
7060
7061     MsiCloseHandle(hrec);
7062     MsiViewClose(hview);
7063     MsiCloseHandle(hview);
7064
7065     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7066     r = run_query(hdb, 0, query);
7067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7068
7069     query = "SELECT * FROM `Table` WHERE `B` = 3";
7070     r = MsiDatabaseOpenView(hdb, query, &hview);
7071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7072     r = MsiViewExecute(hview, 0);
7073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7074
7075     r = MsiViewFetch(hview, &hrec);
7076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7077
7078     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7079     r = run_query(hdb, 0, query);
7080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7081
7082     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7083     r = run_query(hdb, 0, query);
7084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7085
7086     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7088
7089     size = MAX_PATH;
7090     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7092     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7093     ok(size == 5, "Expected 5, got %d\n", size);
7094
7095     r = MsiRecordGetInteger(hrec, 2);
7096     ok(r == 2, "Expected 2, got %d\n", r);
7097
7098     MsiCloseHandle(hrec);
7099     MsiViewClose(hview);
7100     MsiCloseHandle(hview);
7101     MsiCloseHandle(hdb);
7102     DeleteFileA(msifile);
7103 }
7104
7105 static void test_where_viewmodify(void)
7106 {
7107     MSIHANDLE hdb, hview, hrec;
7108     const char *query;
7109     UINT r;
7110
7111     DeleteFile(msifile);
7112
7113     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7115
7116     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7117     r = run_query(hdb, 0, query);
7118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7119
7120     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7121     r = run_query(hdb, 0, query);
7122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7123
7124     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7125     r = run_query(hdb, 0, query);
7126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7127
7128     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7129     r = run_query(hdb, 0, query);
7130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7131
7132     /* `B` = 3 doesn't match, but the view shouldn't be executed */
7133     query = "SELECT * FROM `Table` WHERE `B` = 3";
7134     r = MsiDatabaseOpenView(hdb, query, &hview);
7135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7136
7137     hrec = MsiCreateRecord(2);
7138     MsiRecordSetInteger(hrec, 1, 7);
7139     MsiRecordSetInteger(hrec, 2, 8);
7140
7141     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7143
7144     MsiCloseHandle(hrec);
7145     MsiViewClose(hview);
7146     MsiCloseHandle(hview);
7147
7148     query = "SELECT * FROM `Table` WHERE `A` = 7";
7149     r = MsiDatabaseOpenView(hdb, query, &hview);
7150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7151     r = MsiViewExecute(hview, 0);
7152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7153
7154     r = MsiViewFetch(hview, &hrec);
7155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7156
7157     r = MsiRecordGetInteger(hrec, 1);
7158     ok(r == 7, "Expected 7, got %d\n", r);
7159
7160     r = MsiRecordGetInteger(hrec, 2);
7161     ok(r == 8, "Expected 8, got %d\n", r);
7162
7163     MsiRecordSetInteger(hrec, 2, 9);
7164
7165     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7167
7168     MsiCloseHandle(hrec);
7169     MsiViewClose(hview);
7170     MsiCloseHandle(hview);
7171
7172     query = "SELECT * FROM `Table` WHERE `A` = 7";
7173     r = MsiDatabaseOpenView(hdb, query, &hview);
7174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7175     r = MsiViewExecute(hview, 0);
7176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7177
7178     r = MsiViewFetch(hview, &hrec);
7179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7180
7181     r = MsiRecordGetInteger(hrec, 1);
7182     ok(r == 7, "Expected 7, got %d\n", r);
7183
7184     r = MsiRecordGetInteger(hrec, 2);
7185     ok(r == 9, "Expected 9, got %d\n", r);
7186
7187     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7188     r = run_query(hdb, 0, query);
7189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7190
7191     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7193
7194     r = MsiRecordGetInteger(hrec, 1);
7195     ok(r == 7, "Expected 7, got %d\n", r);
7196
7197     r = MsiRecordGetInteger(hrec, 2);
7198     ok(r == 10, "Expected 10, got %d\n", r);
7199
7200     MsiCloseHandle(hrec);
7201     MsiViewClose(hview);
7202     MsiCloseHandle(hview);
7203     MsiCloseHandle(hdb);
7204 }
7205
7206 static BOOL create_storage(LPCSTR name)
7207 {
7208     WCHAR nameW[MAX_PATH];
7209     IStorage *stg;
7210     IStream *stm;
7211     HRESULT hr;
7212     DWORD count;
7213     BOOL res = FALSE;
7214
7215     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7216     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7217                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7218     if (FAILED(hr))
7219         return FALSE;
7220
7221     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7222                                0, 0, &stm);
7223     if (FAILED(hr))
7224         goto done;
7225
7226     hr = IStream_Write(stm, "stgdata", 8, &count);
7227     if (SUCCEEDED(hr))
7228         res = TRUE;
7229
7230 done:
7231     IStream_Release(stm);
7232     IStorage_Release(stg);
7233
7234     return res;
7235 }
7236
7237 static void test_storages_table(void)
7238 {
7239     MSIHANDLE hdb, hview, hrec;
7240     IStorage *stg, *inner;
7241     IStream *stm;
7242     char file[MAX_PATH];
7243     char buf[MAX_PATH];
7244     WCHAR name[MAX_PATH];
7245     LPCSTR query;
7246     HRESULT hr;
7247     DWORD size;
7248     UINT r;
7249
7250     hdb = create_db();
7251     ok(hdb, "failed to create db\n");
7252
7253     r = MsiDatabaseCommit(hdb);
7254     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7255
7256     MsiCloseHandle(hdb);
7257
7258     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
7259     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7260
7261     /* check the column types */
7262     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7263     ok(hrec, "failed to get column info hrecord\n");
7264     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7265     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7266
7267     MsiCloseHandle(hrec);
7268
7269     /* now try the names */
7270     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7271     ok(hrec, "failed to get column info hrecord\n");
7272     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7273     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7274
7275     MsiCloseHandle(hrec);
7276
7277     create_storage("storage.bin");
7278
7279     hrec = MsiCreateRecord(2);
7280     MsiRecordSetString(hrec, 1, "stgname");
7281
7282     r = MsiRecordSetStream(hrec, 2, "storage.bin");
7283     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7284
7285     DeleteFileA("storage.bin");
7286
7287     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7288     r = MsiDatabaseOpenView(hdb, query, &hview);
7289     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7290
7291     r = MsiViewExecute(hview, hrec);
7292     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7293
7294     MsiCloseHandle(hrec);
7295     MsiViewClose(hview);
7296     MsiCloseHandle(hview);
7297
7298     query = "SELECT `Name`, `Data` FROM `_Storages`";
7299     r = MsiDatabaseOpenView(hdb, query, &hview);
7300     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7301
7302     r = MsiViewExecute(hview, 0);
7303     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7304
7305     r = MsiViewFetch(hview, &hrec);
7306     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7307
7308     size = MAX_PATH;
7309     r = MsiRecordGetString(hrec, 1, file, &size);
7310     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7311     ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7312
7313     size = MAX_PATH;
7314     lstrcpyA(buf, "apple");
7315     r = MsiRecordReadStream(hrec, 2, buf, &size);
7316     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7317     ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7318     ok(size == 0, "Expected 0, got %d\n", size);
7319
7320     MsiCloseHandle(hrec);
7321
7322     r = MsiViewFetch(hview, &hrec);
7323     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7324
7325     MsiViewClose(hview);
7326     MsiCloseHandle(hview);
7327
7328     MsiDatabaseCommit(hdb);
7329     MsiCloseHandle(hdb);
7330
7331     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7332     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7333                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7334     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7335     ok(stg != NULL, "Expected non-NULL storage\n");
7336
7337     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7338     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7339                               NULL, 0, &inner);
7340     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7341     ok(inner != NULL, "Expected non-NULL storage\n");
7342
7343     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7344     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7345     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7346     ok(stm != NULL, "Expected non-NULL stream\n");
7347
7348     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7349     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7350     ok(size == 8, "Expected 8, got %d\n", size);
7351     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7352
7353     IStream_Release(stm);
7354     IStorage_Release(inner);
7355
7356     IStorage_Release(stg);
7357     DeleteFileA(msifile);
7358 }
7359
7360 static void test_dbtopackage(void)
7361 {
7362     MSIHANDLE hdb, hpkg;
7363     CHAR package[12], buf[MAX_PATH];
7364     DWORD size;
7365     UINT r;
7366
7367     /* create an empty database, transact mode */
7368     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7369     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7370
7371     set_summary_info(hdb);
7372
7373     r = create_directory_table(hdb);
7374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7375
7376     r = create_custom_action_table(hdb);
7377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7378
7379     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7381
7382     sprintf(package, "#%u", hdb);
7383     r = MsiOpenPackage(package, &hpkg);
7384     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7385     {
7386         skip("Not enough rights to perform tests\n");
7387         goto error;
7388     }
7389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7390
7391     /* property is not set yet */
7392     size = MAX_PATH;
7393     lstrcpyA(buf, "kiwi");
7394     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7396     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7397     ok(size == 0, "Expected 0, got %d\n", size);
7398
7399     /* run the custom action to set the property */
7400     r = MsiDoAction(hpkg, "SetProp");
7401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7402
7403     /* property is now set */
7404     size = MAX_PATH;
7405     lstrcpyA(buf, "kiwi");
7406     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7408     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7409     ok(size == 5, "Expected 5, got %d\n", size);
7410
7411     MsiCloseHandle(hpkg);
7412
7413     /* reset the package */
7414     r = MsiOpenPackage(package, &hpkg);
7415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7416
7417     /* property is not set anymore */
7418     size = MAX_PATH;
7419     lstrcpyA(buf, "kiwi");
7420     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7422     todo_wine
7423     {
7424         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7425         ok(size == 0, "Expected 0, got %d\n", size);
7426     }
7427
7428     MsiCloseHandle(hdb);
7429     MsiCloseHandle(hpkg);
7430
7431     /* create an empty database, direct mode */
7432     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
7433     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7434
7435     set_summary_info(hdb);
7436
7437     r = create_directory_table(hdb);
7438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7439
7440     r = create_custom_action_table(hdb);
7441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7442
7443     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7445
7446     sprintf(package, "#%u", hdb);
7447     r = MsiOpenPackage(package, &hpkg);
7448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7449
7450     /* property is not set yet */
7451     size = MAX_PATH;
7452     lstrcpyA(buf, "kiwi");
7453     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7455     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7456     ok(size == 0, "Expected 0, got %d\n", size);
7457
7458     /* run the custom action to set the property */
7459     r = MsiDoAction(hpkg, "SetProp");
7460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7461
7462     /* property is now set */
7463     size = MAX_PATH;
7464     lstrcpyA(buf, "kiwi");
7465     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7467     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7468     ok(size == 5, "Expected 5, got %d\n", size);
7469
7470     MsiCloseHandle(hpkg);
7471
7472     /* reset the package */
7473     r = MsiOpenPackage(package, &hpkg);
7474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7475
7476     /* property is not set anymore */
7477     size = MAX_PATH;
7478     lstrcpyA(buf, "kiwi");
7479     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7481     todo_wine
7482     {
7483         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7484         ok(size == 0, "Expected 0, got %d\n", size);
7485     }
7486
7487     MsiCloseHandle(hpkg);
7488
7489 error:
7490     MsiCloseHandle(hdb);
7491     DeleteFileA(msifile);
7492 }
7493
7494 static void test_droptable(void)
7495 {
7496     MSIHANDLE hdb, hview, hrec;
7497     CHAR buf[MAX_PATH];
7498     LPCSTR query;
7499     DWORD size;
7500     UINT r;
7501
7502     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7504
7505     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7506     r = run_query(hdb, 0, query);
7507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7508
7509     query = "SELECT * FROM `One`";
7510     r = do_query(hdb, query, &hrec);
7511     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7512
7513     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7514     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7516     r = MsiViewExecute(hview, 0);
7517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7518
7519     r = MsiViewFetch(hview, &hrec);
7520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7521
7522     size = MAX_PATH;
7523     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7525     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7526
7527     MsiCloseHandle(hrec);
7528     MsiViewClose(hview);
7529     MsiCloseHandle(hview);
7530
7531     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7532     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7534     r = MsiViewExecute(hview, 0);
7535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7536
7537     r = MsiViewFetch(hview, &hrec);
7538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7539
7540     size = MAX_PATH;
7541     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7543     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7544
7545     r = MsiRecordGetInteger(hrec, 2);
7546     ok(r == 1, "Expected 1, got %d\n", r);
7547
7548     size = MAX_PATH;
7549     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7551     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7552
7553     MsiCloseHandle(hrec);
7554
7555     r = MsiViewFetch(hview, &hrec);
7556     ok(r == ERROR_NO_MORE_ITEMS,
7557        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7558
7559     MsiViewClose(hview);
7560     MsiCloseHandle(hview);
7561
7562     query = "DROP `One`";
7563     r = run_query(hdb, 0, query);
7564     ok(r == ERROR_BAD_QUERY_SYNTAX,
7565        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7566
7567     query = "DROP TABLE";
7568     r = run_query(hdb, 0, query);
7569     ok(r == ERROR_BAD_QUERY_SYNTAX,
7570        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7571
7572     query = "DROP TABLE `One`";
7573     hview = 0;
7574     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7575     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7576     r = MsiViewExecute(hview, 0);
7577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7578
7579     r = MsiViewFetch(hview, &hrec);
7580     ok(r == ERROR_FUNCTION_FAILED,
7581        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7582
7583     MsiViewClose(hview);
7584     MsiCloseHandle(hview);
7585
7586     query = "SELECT * FROM `IDontExist`";
7587     r = do_query(hdb, query, &hrec);
7588     ok(r == ERROR_BAD_QUERY_SYNTAX,
7589        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7590
7591     query = "SELECT * FROM `One`";
7592     r = do_query(hdb, query, &hrec);
7593     ok(r == ERROR_BAD_QUERY_SYNTAX,
7594        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7595
7596     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7597     r = run_query(hdb, 0, query);
7598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7599
7600     query = "DROP TABLE One";
7601     r = run_query(hdb, 0, query);
7602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7603
7604     query = "SELECT * FROM `One`";
7605     r = do_query(hdb, query, &hrec);
7606     ok(r == ERROR_BAD_QUERY_SYNTAX,
7607        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7608
7609     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7610     r = do_query(hdb, query, &hrec);
7611     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7612
7613     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7614     r = do_query(hdb, query, &hrec);
7615     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7616
7617     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7618     r = run_query(hdb, 0, query);
7619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7620
7621     query = "SELECT * FROM `One`";
7622     r = do_query(hdb, query, &hrec);
7623     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7624
7625     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7626     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7628     r = MsiViewExecute(hview, 0);
7629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7630
7631     r = MsiViewFetch(hview, &hrec);
7632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7633
7634     size = MAX_PATH;
7635     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7637     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7638
7639     MsiCloseHandle(hrec);
7640     MsiViewClose(hview);
7641     MsiCloseHandle(hview);
7642
7643     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7644     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7646     r = MsiViewExecute(hview, 0);
7647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7648
7649     r = MsiViewFetch(hview, &hrec);
7650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7651
7652     size = MAX_PATH;
7653     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7655     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7656
7657     r = MsiRecordGetInteger(hrec, 2);
7658     ok(r == 1, "Expected 1, got %d\n", r);
7659
7660     size = MAX_PATH;
7661     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7663     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7664
7665     MsiCloseHandle(hrec);
7666
7667     r = MsiViewFetch(hview, &hrec);
7668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7669
7670     size = MAX_PATH;
7671     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7673     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7674
7675     r = MsiRecordGetInteger(hrec, 2);
7676     ok(r == 2, "Expected 2, got %d\n", r);
7677
7678     size = MAX_PATH;
7679     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7681     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7682
7683     MsiCloseHandle(hrec);
7684
7685     r = MsiViewFetch(hview, &hrec);
7686     ok(r == ERROR_NO_MORE_ITEMS,
7687        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7688
7689     MsiViewClose(hview);
7690     MsiCloseHandle(hview);
7691
7692     query = "DROP TABLE One";
7693     r = run_query(hdb, 0, query);
7694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7695
7696     query = "SELECT * FROM `One`";
7697     r = do_query(hdb, query, &hrec);
7698     ok(r == ERROR_BAD_QUERY_SYNTAX,
7699        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7700
7701     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7702     r = do_query(hdb, query, &hrec);
7703     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7704
7705     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7706     r = do_query(hdb, query, &hrec);
7707     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7708
7709     MsiCloseHandle(hdb);
7710     DeleteFileA(msifile);
7711 }
7712
7713 static void test_dbmerge(void)
7714 {
7715     MSIHANDLE hdb, href, hview, hrec;
7716     CHAR buf[MAX_PATH];
7717     LPCSTR query;
7718     DWORD size;
7719     UINT r;
7720
7721     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7723
7724     r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
7725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7726
7727     /* hDatabase is invalid */
7728     r = MsiDatabaseMergeA(0, href, "MergeErrors");
7729     ok(r == ERROR_INVALID_HANDLE,
7730        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7731
7732     /* hDatabaseMerge is invalid */
7733     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7734     ok(r == ERROR_INVALID_HANDLE,
7735        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7736
7737     /* szTableName is NULL */
7738     r = MsiDatabaseMergeA(hdb, href, NULL);
7739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7740
7741     /* szTableName is empty */
7742     r = MsiDatabaseMergeA(hdb, href, "");
7743     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7744
7745     /* both DBs empty, szTableName is valid */
7746     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7748
7749     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7750     r = run_query(hdb, 0, query);
7751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7752
7753     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7754     r = run_query(href, 0, query);
7755     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7756
7757     /* column types don't match */
7758     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7759     ok(r == ERROR_DATATYPE_MISMATCH,
7760        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7761
7762     /* nothing in MergeErrors */
7763     query = "SELECT * FROM `MergeErrors`";
7764     r = do_query(hdb, query, &hrec);
7765     ok(r == ERROR_BAD_QUERY_SYNTAX,
7766        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7767
7768     query = "DROP TABLE `One`";
7769     r = run_query(hdb, 0, query);
7770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7771
7772     query = "DROP TABLE `One`";
7773     r = run_query(href, 0, query);
7774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7775
7776     query = "CREATE TABLE `One` ( "
7777         "`A` CHAR(72), "
7778         "`B` CHAR(56), "
7779         "`C` CHAR(64) LOCALIZABLE, "
7780         "`D` LONGCHAR, "
7781         "`E` CHAR(72) NOT NULL, "
7782         "`F` CHAR(56) NOT NULL, "
7783         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7784         "`H` LONGCHAR NOT NULL "
7785         "PRIMARY KEY `A` )";
7786     r = run_query(hdb, 0, query);
7787     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7788
7789     query = "CREATE TABLE `One` ( "
7790         "`A` CHAR(64), "
7791         "`B` CHAR(64), "
7792         "`C` CHAR(64), "
7793         "`D` CHAR(64), "
7794         "`E` CHAR(64) NOT NULL, "
7795         "`F` CHAR(64) NOT NULL, "
7796         "`G` CHAR(64) NOT NULL, "
7797         "`H` CHAR(64) NOT NULL "
7798         "PRIMARY KEY `A` )";
7799     r = run_query(href, 0, query);
7800     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7801
7802     /* column sting types don't match exactly */
7803     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7804     ok(r == ERROR_SUCCESS,
7805        "Expected ERROR_SUCCESS, got %d\n", r);
7806
7807     /* nothing in MergeErrors */
7808     query = "SELECT * FROM `MergeErrors`";
7809     r = do_query(hdb, query, &hrec);
7810     ok(r == ERROR_BAD_QUERY_SYNTAX,
7811        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7812
7813     query = "DROP TABLE `One`";
7814     r = run_query(hdb, 0, query);
7815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7816
7817     query = "DROP TABLE `One`";
7818     r = run_query(href, 0, query);
7819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7820
7821     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7822     r = run_query(hdb, 0, query);
7823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7824
7825     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
7826     r = run_query(href, 0, query);
7827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7828
7829     /* column names don't match */
7830     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7831     ok(r == ERROR_DATATYPE_MISMATCH,
7832        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7833
7834     /* nothing in MergeErrors */
7835     query = "SELECT * FROM `MergeErrors`";
7836     r = do_query(hdb, query, &hrec);
7837     ok(r == ERROR_BAD_QUERY_SYNTAX,
7838        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7839
7840     query = "DROP TABLE `One`";
7841     r = run_query(hdb, 0, query);
7842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7843
7844     query = "DROP TABLE `One`";
7845     r = run_query(href, 0, query);
7846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7847
7848     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7849     r = run_query(hdb, 0, query);
7850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7851
7852     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
7853     r = run_query(href, 0, query);
7854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7855
7856     /* primary keys don't match */
7857     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7858     ok(r == ERROR_DATATYPE_MISMATCH,
7859        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7860
7861     /* nothing in MergeErrors */
7862     query = "SELECT * FROM `MergeErrors`";
7863     r = do_query(hdb, query, &hrec);
7864     ok(r == ERROR_BAD_QUERY_SYNTAX,
7865        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7866
7867     query = "DROP TABLE `One`";
7868     r = run_query(hdb, 0, query);
7869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7870
7871     query = "DROP TABLE `One`";
7872     r = run_query(href, 0, query);
7873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7874
7875     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7876     r = run_query(hdb, 0, query);
7877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7878
7879     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
7880     r = run_query(href, 0, query);
7881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7882
7883     /* number of primary keys doesn't match */
7884     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7885     ok(r == ERROR_DATATYPE_MISMATCH,
7886        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7887
7888     /* nothing in MergeErrors */
7889     query = "SELECT * FROM `MergeErrors`";
7890     r = do_query(hdb, query, &hrec);
7891     ok(r == ERROR_BAD_QUERY_SYNTAX,
7892        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7893
7894     query = "DROP TABLE `One`";
7895     r = run_query(hdb, 0, query);
7896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7897
7898     query = "DROP TABLE `One`";
7899     r = run_query(href, 0, query);
7900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7901
7902     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
7903     r = run_query(hdb, 0, query);
7904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7905
7906     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7907     r = run_query(href, 0, query);
7908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7909
7910     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
7911     r = run_query(href, 0, query);
7912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7913
7914     /* number of columns doesn't match */
7915     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7917
7918     query = "SELECT * FROM `One`";
7919     r = do_query(hdb, query, &hrec);
7920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7921
7922     r = MsiRecordGetInteger(hrec, 1);
7923     ok(r == 1, "Expected 1, got %d\n", r);
7924
7925     r = MsiRecordGetInteger(hrec, 2);
7926     ok(r == 2, "Expected 2, got %d\n", r);
7927
7928     r = MsiRecordGetInteger(hrec, 3);
7929     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
7930
7931     MsiCloseHandle(hrec);
7932
7933     /* nothing in MergeErrors */
7934     query = "SELECT * FROM `MergeErrors`";
7935     r = do_query(hdb, query, &hrec);
7936     ok(r == ERROR_BAD_QUERY_SYNTAX,
7937        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7938
7939     query = "DROP TABLE `One`";
7940     r = run_query(hdb, 0, query);
7941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7942
7943     query = "DROP TABLE `One`";
7944     r = run_query(href, 0, query);
7945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7946
7947     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7948     r = run_query(hdb, 0, query);
7949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7950
7951     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
7952     r = run_query(href, 0, query);
7953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7954
7955     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
7956     r = run_query(href, 0, query);
7957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7958
7959     /* number of columns doesn't match */
7960     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7962
7963     query = "SELECT * FROM `One`";
7964     r = do_query(hdb, query, &hrec);
7965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7966
7967     r = MsiRecordGetInteger(hrec, 1);
7968     ok(r == 1, "Expected 1, got %d\n", r);
7969
7970     r = MsiRecordGetInteger(hrec, 2);
7971     ok(r == 2, "Expected 2, got %d\n", r);
7972
7973     r = MsiRecordGetInteger(hrec, 3);
7974     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
7975
7976     MsiCloseHandle(hrec);
7977
7978     /* nothing in MergeErrors */
7979     query = "SELECT * FROM `MergeErrors`";
7980     r = do_query(hdb, query, &hrec);
7981     ok(r == ERROR_BAD_QUERY_SYNTAX,
7982        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7983
7984     query = "DROP TABLE `One`";
7985     r = run_query(hdb, 0, query);
7986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7987
7988     query = "DROP TABLE `One`";
7989     r = run_query(href, 0, query);
7990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7991
7992     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7993     r = run_query(hdb, 0, query);
7994     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7995
7996     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
7997     r = run_query(hdb, 0, query);
7998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7999
8000     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8001     r = run_query(hdb, 0, query);
8002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8003
8004     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8005     r = run_query(href, 0, query);
8006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8007
8008     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
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 ( 2, 3 )";
8013     r = run_query(href, 0, query);
8014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8015
8016     /* primary keys match, rows do not */
8017     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8018     ok(r == ERROR_FUNCTION_FAILED,
8019        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8020
8021     /* nothing in MergeErrors */
8022     query = "SELECT * FROM `MergeErrors`";
8023     r = do_query(hdb, query, &hrec);
8024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8025
8026     size = MAX_PATH;
8027     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8029     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8030
8031     r = MsiRecordGetInteger(hrec, 2);
8032     ok(r == 2, "Expected 2, got %d\n", r);
8033
8034     MsiCloseHandle(hrec);
8035
8036     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8038
8039     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8041
8042     size = MAX_PATH;
8043     r = MsiRecordGetString(hrec, 1, buf, &size);
8044     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8045
8046     size = MAX_PATH;
8047     r = MsiRecordGetString(hrec, 2, buf, &size);
8048     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8049        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8050
8051     MsiCloseHandle(hrec);
8052
8053     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8055
8056     size = MAX_PATH;
8057     r = MsiRecordGetString(hrec, 1, buf, &size);
8058     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8059
8060     size = MAX_PATH;
8061     r = MsiRecordGetString(hrec, 2, buf, &size);
8062     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8063
8064     MsiCloseHandle(hrec);
8065     MsiViewClose(hview);
8066     MsiCloseHandle(hview);
8067
8068     query = "DROP TABLE `MergeErrors`";
8069     r = run_query(hdb, 0, query);
8070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8071
8072     query = "DROP TABLE `One`";
8073     r = run_query(hdb, 0, query);
8074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8075
8076     query = "DROP TABLE `One`";
8077     r = run_query(href, 0, query);
8078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8079
8080     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8081     r = run_query(href, 0, query);
8082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8083
8084     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8085     r = run_query(href, 0, query);
8086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8087
8088     /* table from merged database is not in target database */
8089     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8091
8092     query = "SELECT * FROM `One`";
8093     r = do_query(hdb, query, &hrec);
8094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8095
8096     r = MsiRecordGetInteger(hrec, 1);
8097     ok(r == 1, "Expected 1, got %d\n", r);
8098
8099     size = MAX_PATH;
8100     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8102     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8103
8104     MsiCloseHandle(hrec);
8105
8106     /* nothing in MergeErrors */
8107     query = "SELECT * FROM `MergeErrors`";
8108     r = do_query(hdb, query, &hrec);
8109     ok(r == ERROR_BAD_QUERY_SYNTAX,
8110        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8111
8112     query = "DROP TABLE `One`";
8113     r = run_query(hdb, 0, query);
8114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8115
8116     query = "DROP TABLE `One`";
8117     r = run_query(href, 0, query);
8118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8119
8120     query = "CREATE TABLE `One` ( "
8121             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8122     r = run_query(hdb, 0, query);
8123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8124
8125     query = "CREATE TABLE `One` ( "
8126             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8127     r = run_query(href, 0, query);
8128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8129
8130     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8131     r = run_query(href, 0, query);
8132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8133
8134     /* primary key is string */
8135     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8137
8138     query = "SELECT * FROM `One`";
8139     r = do_query(hdb, query, &hrec);
8140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8141
8142     size = MAX_PATH;
8143     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8144     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8145     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8146
8147     r = MsiRecordGetInteger(hrec, 2);
8148     ok(r == 1, "Expected 1, got %d\n", r);
8149
8150     MsiCloseHandle(hrec);
8151
8152     /* nothing in MergeErrors */
8153     query = "SELECT * FROM `MergeErrors`";
8154     r = do_query(hdb, query, &hrec);
8155     ok(r == ERROR_BAD_QUERY_SYNTAX,
8156        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8157
8158     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8159
8160     GetCurrentDirectoryA(MAX_PATH, buf);
8161     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8162     todo_wine
8163     {
8164         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8165     }
8166
8167     query = "DROP TABLE `One`";
8168     r = run_query(hdb, 0, query);
8169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8170
8171     query = "DROP TABLE `One`";
8172     r = run_query(href, 0, query);
8173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8174
8175     query = "CREATE TABLE `One` ( "
8176             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8177     r = run_query(hdb, 0, query);
8178     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8179
8180     query = "CREATE TABLE `One` ( "
8181             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8182     r = run_query(href, 0, query);
8183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8184
8185     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8186     r = run_query(href, 0, query);
8187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8188
8189     /* code page does not match */
8190     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8192
8193     query = "SELECT * FROM `One`";
8194     r = do_query(hdb, query, &hrec);
8195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8196
8197     r = MsiRecordGetInteger(hrec, 1);
8198     ok(r == 1, "Expected 1, got %d\n", r);
8199
8200     size = MAX_PATH;
8201     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8203     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8204
8205     MsiCloseHandle(hrec);
8206
8207     /* nothing in MergeErrors */
8208     query = "SELECT * FROM `MergeErrors`";
8209     r = do_query(hdb, query, &hrec);
8210     ok(r == ERROR_BAD_QUERY_SYNTAX,
8211        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8212
8213     query = "DROP TABLE `One`";
8214     r = run_query(hdb, 0, query);
8215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8216
8217     query = "DROP TABLE `One`";
8218     r = run_query(href, 0, query);
8219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8220
8221     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8222     r = run_query(hdb, 0, query);
8223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8224
8225     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8226     r = run_query(href, 0, query);
8227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8228
8229     create_file("binary.dat");
8230     hrec = MsiCreateRecord(1);
8231     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8232
8233     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8234     r = run_query(href, hrec, query);
8235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8236
8237     MsiCloseHandle(hrec);
8238
8239     /* binary data to merge */
8240     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8242
8243     query = "SELECT * FROM `One`";
8244     r = do_query(hdb, query, &hrec);
8245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8246
8247     r = MsiRecordGetInteger(hrec, 1);
8248     ok(r == 1, "Expected 1, got %d\n", r);
8249
8250     size = MAX_PATH;
8251     ZeroMemory(buf, MAX_PATH);
8252     r = MsiRecordReadStream(hrec, 2, buf, &size);
8253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8254     ok(!lstrcmpA(buf, "binary.dat\n"),
8255        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8256
8257     MsiCloseHandle(hrec);
8258
8259     /* nothing in MergeErrors */
8260     query = "SELECT * FROM `MergeErrors`";
8261     r = do_query(hdb, query, &hrec);
8262     ok(r == ERROR_BAD_QUERY_SYNTAX,
8263        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8264
8265     query = "DROP TABLE `One`";
8266     r = run_query(hdb, 0, query);
8267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8268
8269     query = "DROP TABLE `One`";
8270     r = run_query(href, 0, query);
8271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8272
8273     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8274     r = run_query(hdb, 0, query);
8275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8276     r = run_query(href, 0, query);
8277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8278
8279     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8280     r = run_query(href, 0, query);
8281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8282
8283     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8284     r = run_query(href, 0, query);
8285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8286
8287     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8289
8290     query = "SELECT * FROM `One`";
8291     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8293     r = MsiViewExecute(hview, 0);
8294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8295
8296     r = MsiViewFetch(hview, &hrec);
8297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8298
8299     r = MsiRecordGetInteger(hrec, 1);
8300     ok(r == 1, "Expected 1, got %d\n", r);
8301
8302     size = MAX_PATH;
8303     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8305     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8306
8307     MsiCloseHandle(hrec);
8308
8309     r = MsiViewFetch(hview, &hrec);
8310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8311
8312     r = MsiRecordGetInteger(hrec, 1);
8313     ok(r == 2, "Expected 2, got %d\n", r);
8314
8315     size = MAX_PATH;
8316     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8318     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8319
8320     MsiCloseHandle(hrec);
8321
8322     r = MsiViewFetch(hview, &hrec);
8323     ok(r == ERROR_NO_MORE_ITEMS,
8324        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8325
8326     MsiViewClose(hview);
8327     MsiCloseHandle(hview);
8328
8329     MsiCloseHandle(hdb);
8330     MsiCloseHandle(href);
8331     DeleteFileA(msifile);
8332     DeleteFileA("refdb.msi");
8333     DeleteFileA("codepage.idt");
8334     DeleteFileA("binary.dat");
8335 }
8336
8337 static void test_select_with_tablenames(void)
8338 {
8339     MSIHANDLE hdb, view, rec;
8340     LPCSTR query;
8341     UINT r;
8342     int i;
8343
8344     int vals[4][2] = {
8345         {1,12},
8346         {4,12},
8347         {1,15},
8348         {4,15}};
8349
8350     hdb = create_db();
8351     ok(hdb, "failed to create db\n");
8352
8353     /* Build a pair of tables with the same column names, but unique data */
8354     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8355     r = run_query(hdb, 0, query);
8356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8357
8358     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8359     r = run_query(hdb, 0, query);
8360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8361
8362     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8363     r = run_query(hdb, 0, query);
8364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8365
8366     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8367     r = run_query(hdb, 0, query);
8368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8369
8370     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8371     r = run_query(hdb, 0, query);
8372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8373
8374     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8375     r = run_query(hdb, 0, query);
8376     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8377
8378
8379     /* Test that selection based on prefixing the column with the table
8380      * actually selects the right data */
8381
8382     query = "SELECT T1.A, T2.B FROM T1,T2";
8383     r = MsiDatabaseOpenView(hdb, query, &view);
8384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8385     r = MsiViewExecute(view, 0);
8386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8387
8388     for (i = 0; i < 4; i++)
8389     {
8390         r = MsiViewFetch(view, &rec);
8391         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8392
8393         r = MsiRecordGetInteger(rec, 1);
8394         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8395
8396         r = MsiRecordGetInteger(rec, 2);
8397         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8398
8399         MsiCloseHandle(rec);
8400     }
8401
8402     r = MsiViewFetch(view, &rec);
8403     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8404
8405     MsiViewClose(view);
8406     MsiCloseHandle(view);
8407     MsiCloseHandle(hdb);
8408     DeleteFileA(msifile);
8409 }
8410
8411 static const UINT ordervals[6][3] =
8412 {
8413     { MSI_NULL_INTEGER, 12, 13 },
8414     { 1, 2, 3 },
8415     { 6, 4, 5 },
8416     { 8, 9, 7 },
8417     { 10, 11, MSI_NULL_INTEGER },
8418     { 14, MSI_NULL_INTEGER, 15 }
8419 };
8420
8421 static void test_insertorder(void)
8422 {
8423     MSIHANDLE hdb, view, rec;
8424     LPCSTR query;
8425     UINT r;
8426     int i;
8427
8428     hdb = create_db();
8429     ok(hdb, "failed to create db\n");
8430
8431     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8432     r = run_query(hdb, 0, query);
8433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8434
8435     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8436     r = run_query(hdb, 0, query);
8437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8438
8439     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8440     r = run_query(hdb, 0, query);
8441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8442
8443     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8444     r = run_query(hdb, 0, query);
8445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8446
8447     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8448     r = run_query(hdb, 0, query);
8449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8450
8451     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8452     r = run_query(hdb, 0, query);
8453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8454
8455     /* fails because the primary key already
8456      * has an MSI_NULL_INTEGER value set above
8457      */
8458     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8459     r = run_query(hdb, 0, query);
8460     ok(r == ERROR_FUNCTION_FAILED,
8461        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8462
8463     /* replicate the error where primary key is set twice */
8464     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8465     r = run_query(hdb, 0, query);
8466     ok(r == ERROR_FUNCTION_FAILED,
8467        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8468
8469     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8470     r = run_query(hdb, 0, query);
8471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8472
8473     query = "INSERT INTO `T` VALUES ( 16 )";
8474     r = run_query(hdb, 0, query);
8475     ok(r == ERROR_BAD_QUERY_SYNTAX,
8476        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8477
8478     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8479     r = run_query(hdb, 0, query);
8480     ok(r == ERROR_BAD_QUERY_SYNTAX,
8481        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8482
8483     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8484     r = run_query(hdb, 0, query);
8485     ok(r == ERROR_BAD_QUERY_SYNTAX,
8486        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8487
8488     query = "SELECT * FROM `T`";
8489     r = MsiDatabaseOpenView(hdb, query, &view);
8490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8491     r = MsiViewExecute(view, 0);
8492     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8493
8494     for (i = 0; i < 6; i++)
8495     {
8496         r = MsiViewFetch(view, &rec);
8497         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8498
8499         r = MsiRecordGetInteger(rec, 1);
8500         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8501
8502         r = MsiRecordGetInteger(rec, 2);
8503         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8504
8505         r = MsiRecordGetInteger(rec, 3);
8506         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8507
8508         MsiCloseHandle(rec);
8509     }
8510
8511     r = MsiViewFetch(view, &rec);
8512     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8513
8514     MsiViewClose(view);
8515     MsiCloseHandle(view);
8516
8517     query = "DELETE FROM `T` WHERE `A` IS NULL";
8518     r = run_query(hdb, 0, query);
8519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8520
8521     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8522     r = run_query(hdb, 0, query);
8523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8524
8525     query = "SELECT * FROM `T`";
8526     r = MsiDatabaseOpenView(hdb, query, &view);
8527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8528     r = MsiViewExecute(view, 0);
8529     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8530
8531     for (i = 0; i < 6; i++)
8532     {
8533         r = MsiViewFetch(view, &rec);
8534         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8535
8536         r = MsiRecordGetInteger(rec, 1);
8537         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8538
8539         r = MsiRecordGetInteger(rec, 2);
8540         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8541
8542         r = MsiRecordGetInteger(rec, 3);
8543         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8544
8545         MsiCloseHandle(rec);
8546     }
8547
8548     r = MsiViewFetch(view, &rec);
8549     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8550
8551     MsiViewClose(view);
8552     MsiCloseHandle(view);
8553     MsiCloseHandle(hdb);
8554     DeleteFileA(msifile);
8555 }
8556
8557 static void test_columnorder(void)
8558 {
8559     MSIHANDLE hdb, view, rec;
8560     char buf[MAX_PATH];
8561     LPCSTR query;
8562     DWORD sz;
8563     UINT r;
8564
8565     hdb = create_db();
8566     ok(hdb, "failed to create db\n");
8567
8568     /* Each column is a slot:
8569      * ---------------------
8570      * | B | C | A | E | D |
8571      * ---------------------
8572      *
8573      * When a column is selected as a primary key,
8574      * the column occupying the nth primary key slot is swapped
8575      * with the current position of the primary key in question:
8576      *
8577      * set primary key `D`
8578      * ---------------------    ---------------------
8579      * | B | C | A | E | D | -> | D | C | A | E | B |
8580      * ---------------------    ---------------------
8581      *
8582      * set primary key `E`
8583      * ---------------------    ---------------------
8584      * | D | C | A | E | B | -> | D | E | A | C | B |
8585      * ---------------------    ---------------------
8586      */
8587
8588     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8589             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8590             "PRIMARY KEY `D`, `E`)";
8591     r = run_query(hdb, 0, query);
8592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8593
8594     query = "SELECT * FROM `T`";
8595     r = MsiDatabaseOpenView(hdb, query, &view);
8596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8597
8598     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8600
8601     sz = MAX_PATH;
8602     lstrcpyA(buf, "kiwi");
8603     r = MsiRecordGetString(rec, 1, buf, &sz);
8604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8605     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8606
8607     sz = MAX_PATH;
8608     lstrcpyA(buf, "kiwi");
8609     r = MsiRecordGetString(rec, 2, buf, &sz);
8610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8611     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8612
8613     sz = MAX_PATH;
8614     lstrcpyA(buf, "kiwi");
8615     r = MsiRecordGetString(rec, 3, buf, &sz);
8616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8617     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8618
8619     sz = MAX_PATH;
8620     lstrcpyA(buf, "kiwi");
8621     r = MsiRecordGetString(rec, 4, buf, &sz);
8622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8623     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8624
8625     sz = MAX_PATH;
8626     lstrcpyA(buf, "kiwi");
8627     r = MsiRecordGetString(rec, 5, buf, &sz);
8628     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8629     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8630
8631     MsiCloseHandle(rec);
8632
8633     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8635
8636     sz = MAX_PATH;
8637     lstrcpyA(buf, "kiwi");
8638     r = MsiRecordGetString(rec, 1, buf, &sz);
8639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8640     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8641
8642     sz = MAX_PATH;
8643     lstrcpyA(buf, "kiwi");
8644     r = MsiRecordGetString(rec, 2, buf, &sz);
8645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8646     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8647
8648     sz = MAX_PATH;
8649     lstrcpyA(buf, "kiwi");
8650     r = MsiRecordGetString(rec, 3, buf, &sz);
8651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8652     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8653
8654     sz = MAX_PATH;
8655     lstrcpyA(buf, "kiwi");
8656     r = MsiRecordGetString(rec, 4, buf, &sz);
8657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8658     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8659
8660     sz = MAX_PATH;
8661     lstrcpyA(buf, "kiwi");
8662     r = MsiRecordGetString(rec, 5, buf, &sz);
8663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8664     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8665
8666     MsiCloseHandle(rec);
8667     MsiViewClose(view);
8668     MsiCloseHandle(view);
8669
8670     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8671             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8672     r = run_query(hdb, 0, query);
8673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8674
8675     query = "SELECT * FROM `T`";
8676     r = do_query(hdb, query, &rec);
8677
8678     sz = MAX_PATH;
8679     lstrcpyA(buf, "kiwi");
8680     r = MsiRecordGetString(rec, 1, buf, &sz);
8681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8682     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8683
8684     r = MsiRecordGetInteger(rec, 2);
8685     ok(r == 3, "Expected 3, got %d\n", r);
8686
8687     sz = MAX_PATH;
8688     lstrcpyA(buf, "kiwi");
8689     r = MsiRecordGetString(rec, 3, buf, &sz);
8690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8691     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8692
8693     r = MsiRecordGetInteger(rec, 4);
8694     ok(r == 2, "Expected 2, got %d\n", r);
8695
8696     r = MsiRecordGetInteger(rec, 5);
8697     ok(r == 1, "Expected 1, got %d\n", r);
8698
8699     MsiCloseHandle(rec);
8700
8701     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8702     r = MsiDatabaseOpenView(hdb, query, &view);
8703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8704     r = MsiViewExecute(view, 0);
8705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8706
8707     r = MsiViewFetch(view, &rec);
8708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8709
8710     sz = MAX_PATH;
8711     lstrcpyA(buf, "kiwi");
8712     r = MsiRecordGetString(rec, 1, buf, &sz);
8713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8714     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8715
8716     r = MsiRecordGetInteger(rec, 2);
8717     ok(r == 1, "Expected 1, got %d\n", r);
8718
8719     sz = MAX_PATH;
8720     lstrcpyA(buf, "kiwi");
8721     r = MsiRecordGetString(rec, 3, buf, &sz);
8722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8723     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8724
8725     MsiCloseHandle(rec);
8726
8727     r = MsiViewFetch(view, &rec);
8728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8729
8730     sz = MAX_PATH;
8731     lstrcpyA(buf, "kiwi");
8732     r = MsiRecordGetString(rec, 1, buf, &sz);
8733     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8734     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8735
8736     r = MsiRecordGetInteger(rec, 2);
8737     ok(r == 2, "Expected 2, got %d\n", r);
8738
8739     sz = MAX_PATH;
8740     lstrcpyA(buf, "kiwi");
8741     r = MsiRecordGetString(rec, 3, buf, &sz);
8742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8743     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8744
8745     MsiCloseHandle(rec);
8746
8747     r = MsiViewFetch(view, &rec);
8748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8749
8750     sz = MAX_PATH;
8751     lstrcpyA(buf, "kiwi");
8752     r = MsiRecordGetString(rec, 1, buf, &sz);
8753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8754     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8755
8756     r = MsiRecordGetInteger(rec, 2);
8757     ok(r == 3, "Expected 3, got %d\n", r);
8758
8759     sz = MAX_PATH;
8760     lstrcpyA(buf, "kiwi");
8761     r = MsiRecordGetString(rec, 3, buf, &sz);
8762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8763     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8764
8765     MsiCloseHandle(rec);
8766
8767     r = MsiViewFetch(view, &rec);
8768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8769
8770     sz = MAX_PATH;
8771     lstrcpyA(buf, "kiwi");
8772     r = MsiRecordGetString(rec, 1, buf, &sz);
8773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8774     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8775
8776     r = MsiRecordGetInteger(rec, 2);
8777     ok(r == 4, "Expected 4, got %d\n", r);
8778
8779     sz = MAX_PATH;
8780     lstrcpyA(buf, "kiwi");
8781     r = MsiRecordGetString(rec, 3, buf, &sz);
8782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8783     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8784
8785     MsiCloseHandle(rec);
8786
8787     r = MsiViewFetch(view, &rec);
8788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8789
8790     sz = MAX_PATH;
8791     lstrcpyA(buf, "kiwi");
8792     r = MsiRecordGetString(rec, 1, buf, &sz);
8793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8794     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8795
8796     r = MsiRecordGetInteger(rec, 2);
8797     ok(r == 5, "Expected 5, got %d\n", r);
8798
8799     sz = MAX_PATH;
8800     lstrcpyA(buf, "kiwi");
8801     r = MsiRecordGetString(rec, 3, buf, &sz);
8802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8803     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8804
8805     MsiCloseHandle(rec);
8806
8807     r = MsiViewFetch(view, &rec);
8808     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8809
8810     MsiViewClose(view);
8811     MsiCloseHandle(view);
8812
8813     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8814             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8815             "PRIMARY KEY `C`, `A`, `D`)";
8816     r = run_query(hdb, 0, query);
8817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8818
8819     query = "SELECT * FROM `Z`";
8820     r = MsiDatabaseOpenView(hdb, query, &view);
8821     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8822
8823     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8825
8826     sz = MAX_PATH;
8827     lstrcpyA(buf, "kiwi");
8828     r = MsiRecordGetString(rec, 1, buf, &sz);
8829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8830     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8831
8832     sz = MAX_PATH;
8833     lstrcpyA(buf, "kiwi");
8834     r = MsiRecordGetString(rec, 2, buf, &sz);
8835     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8836     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8837
8838     sz = MAX_PATH;
8839     lstrcpyA(buf, "kiwi");
8840     r = MsiRecordGetString(rec, 3, buf, &sz);
8841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8842     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8843
8844     sz = MAX_PATH;
8845     lstrcpyA(buf, "kiwi");
8846     r = MsiRecordGetString(rec, 4, buf, &sz);
8847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8848     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8849
8850     sz = MAX_PATH;
8851     lstrcpyA(buf, "kiwi");
8852     r = MsiRecordGetString(rec, 5, buf, &sz);
8853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8854     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8855
8856     MsiCloseHandle(rec);
8857
8858     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8860
8861     sz = MAX_PATH;
8862     lstrcpyA(buf, "kiwi");
8863     r = MsiRecordGetString(rec, 1, buf, &sz);
8864     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8865     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8866
8867     sz = MAX_PATH;
8868     lstrcpyA(buf, "kiwi");
8869     r = MsiRecordGetString(rec, 2, buf, &sz);
8870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8871     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8872
8873     sz = MAX_PATH;
8874     lstrcpyA(buf, "kiwi");
8875     r = MsiRecordGetString(rec, 3, buf, &sz);
8876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8877     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8878
8879     sz = MAX_PATH;
8880     lstrcpyA(buf, "kiwi");
8881     r = MsiRecordGetString(rec, 4, buf, &sz);
8882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8883     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8884
8885     sz = MAX_PATH;
8886     lstrcpyA(buf, "kiwi");
8887     r = MsiRecordGetString(rec, 5, buf, &sz);
8888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8889     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8890
8891     MsiCloseHandle(rec);
8892     MsiViewClose(view);
8893     MsiCloseHandle(view);
8894
8895     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
8896             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8897     r = run_query(hdb, 0, query);
8898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8899
8900     query = "SELECT * FROM `Z`";
8901     r = do_query(hdb, query, &rec);
8902
8903     r = MsiRecordGetInteger(rec, 1);
8904     ok(r == 2, "Expected 2, got %d\n", r);
8905
8906     sz = MAX_PATH;
8907     lstrcpyA(buf, "kiwi");
8908     r = MsiRecordGetString(rec, 2, buf, &sz);
8909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8910     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8911
8912     sz = MAX_PATH;
8913     lstrcpyA(buf, "kiwi");
8914     r = MsiRecordGetString(rec, 3, buf, &sz);
8915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8916     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8917
8918     r = MsiRecordGetInteger(rec, 4);
8919     ok(r == 3, "Expected 3, got %d\n", r);
8920
8921     r = MsiRecordGetInteger(rec, 5);
8922     ok(r == 1, "Expected 1, got %d\n", r);
8923
8924     MsiCloseHandle(rec);
8925
8926     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8927     r = MsiDatabaseOpenView(hdb, query, &view);
8928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8929     r = MsiViewExecute(view, 0);
8930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8931
8932     r = MsiViewFetch(view, &rec);
8933     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8934
8935     sz = MAX_PATH;
8936     lstrcpyA(buf, "kiwi");
8937     r = MsiRecordGetString(rec, 1, buf, &sz);
8938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8939     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8940
8941     r = MsiRecordGetInteger(rec, 2);
8942     ok(r == 1, "Expected 1, got %d\n", r);
8943
8944     sz = MAX_PATH;
8945     lstrcpyA(buf, "kiwi");
8946     r = MsiRecordGetString(rec, 3, buf, &sz);
8947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8948     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8949
8950     MsiCloseHandle(rec);
8951
8952     r = MsiViewFetch(view, &rec);
8953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8954
8955     sz = MAX_PATH;
8956     lstrcpyA(buf, "kiwi");
8957     r = MsiRecordGetString(rec, 1, buf, &sz);
8958     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8959     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8960
8961     r = MsiRecordGetInteger(rec, 2);
8962     ok(r == 2, "Expected 2, got %d\n", r);
8963
8964     sz = MAX_PATH;
8965     lstrcpyA(buf, "kiwi");
8966     r = MsiRecordGetString(rec, 3, buf, &sz);
8967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8968     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8969
8970     MsiCloseHandle(rec);
8971
8972     r = MsiViewFetch(view, &rec);
8973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8974
8975     sz = MAX_PATH;
8976     lstrcpyA(buf, "kiwi");
8977     r = MsiRecordGetString(rec, 1, buf, &sz);
8978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8979     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8980
8981     r = MsiRecordGetInteger(rec, 2);
8982     ok(r == 3, "Expected 3, got %d\n", r);
8983
8984     sz = MAX_PATH;
8985     lstrcpyA(buf, "kiwi");
8986     r = MsiRecordGetString(rec, 3, buf, &sz);
8987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8988     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8989
8990     MsiCloseHandle(rec);
8991
8992     r = MsiViewFetch(view, &rec);
8993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8994
8995     sz = MAX_PATH;
8996     lstrcpyA(buf, "kiwi");
8997     r = MsiRecordGetString(rec, 1, buf, &sz);
8998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8999     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9000
9001     r = MsiRecordGetInteger(rec, 2);
9002     ok(r == 4, "Expected 4, got %d\n", r);
9003
9004     sz = MAX_PATH;
9005     lstrcpyA(buf, "kiwi");
9006     r = MsiRecordGetString(rec, 3, buf, &sz);
9007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9008     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9009
9010     MsiCloseHandle(rec);
9011
9012     r = MsiViewFetch(view, &rec);
9013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9014
9015     sz = MAX_PATH;
9016     lstrcpyA(buf, "kiwi");
9017     r = MsiRecordGetString(rec, 1, buf, &sz);
9018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9019     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9020
9021     r = MsiRecordGetInteger(rec, 2);
9022     ok(r == 5, "Expected 5, got %d\n", r);
9023
9024     sz = MAX_PATH;
9025     lstrcpyA(buf, "kiwi");
9026     r = MsiRecordGetString(rec, 3, buf, &sz);
9027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9028     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9029
9030     MsiCloseHandle(rec);
9031
9032     r = MsiViewFetch(view, &rec);
9033     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9034
9035     MsiViewClose(view);
9036     MsiCloseHandle(view);
9037
9038     MsiCloseHandle(hdb);
9039     DeleteFileA(msifile);
9040 }
9041
9042 static void test_createtable(void)
9043 {
9044     MSIHANDLE hdb, htab = 0, hrec = 0;
9045     LPCSTR query;
9046     UINT res;
9047     DWORD size;
9048     char buffer[0x20];
9049
9050     hdb = create_db();
9051     ok(hdb, "failed to create db\n");
9052
9053     query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9054     res = MsiDatabaseOpenView( hdb, query, &htab );
9055     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9056     if(res == ERROR_SUCCESS )
9057     {
9058         res = MsiViewExecute( htab, hrec );
9059         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9060
9061         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9062         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9063
9064         size = sizeof(buffer);
9065         res = MsiRecordGetString(hrec, 1, buffer, &size );
9066         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9067         MsiCloseHandle( hrec );
9068
9069         res = MsiViewClose( htab );
9070         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9071
9072         res = MsiCloseHandle( htab );
9073         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9074     }
9075
9076     query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9077     res = MsiDatabaseOpenView( hdb, query, &htab );
9078     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9079     if(res == ERROR_SUCCESS )
9080     {
9081         res = MsiViewExecute( htab, 0 );
9082         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9083
9084         res = MsiViewClose( htab );
9085         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9086
9087         res = MsiCloseHandle( htab );
9088         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9089
9090         query = "SELECT * FROM `a`";
9091         res = MsiDatabaseOpenView( hdb, query, &htab );
9092         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9093
9094         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9095         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9096
9097         buffer[0] = 0;
9098         size = sizeof(buffer);
9099         res = MsiRecordGetString(hrec, 1, buffer, &size );
9100         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9101         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9102         MsiCloseHandle( hrec );
9103
9104         res = MsiViewClose( htab );
9105         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9106
9107         res = MsiCloseHandle( htab );
9108         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9109
9110         res = MsiDatabaseCommit(hdb);
9111         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9112
9113         res = MsiCloseHandle(hdb);
9114         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9115
9116         res = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
9117         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9118
9119         query = "SELECT * FROM `a`";
9120         res = MsiDatabaseOpenView( hdb, query, &htab );
9121         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9122
9123         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9124         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9125
9126         buffer[0] = 0;
9127         size = sizeof(buffer);
9128         res = MsiRecordGetString(hrec, 1, buffer, &size );
9129         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9130         todo_wine ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9131
9132         res = MsiCloseHandle( hrec );
9133         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9134
9135         res = MsiViewClose( htab );
9136         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9137
9138         res = MsiCloseHandle( htab );
9139         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9140     }
9141
9142     res = MsiDatabaseCommit(hdb);
9143     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9144
9145     res = MsiCloseHandle(hdb);
9146     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9147
9148     DeleteFileA(msifile);
9149 }
9150
9151
9152 START_TEST(db)
9153 {
9154     test_msidatabase();
9155     test_msiinsert();
9156     test_msidecomposedesc();
9157     test_msibadqueries();
9158     test_viewmodify();
9159     test_viewgetcolumninfo();
9160     test_getcolinfo();
9161     test_msiexport();
9162     test_longstrings();
9163     test_streamtable();
9164     test_binary();
9165     test_where_not_in_selected();
9166     test_where();
9167     test_msiimport();
9168     test_binary_import();
9169     test_markers();
9170     test_handle_limit();
9171     test_try_transform();
9172     test_join();
9173     test_temporary_table();
9174     test_alter();
9175     test_integers();
9176     test_update();
9177     test_special_tables();
9178     test_tables_order();
9179     test_rows_order();
9180     test_select_markers();
9181     test_viewmodify_update();
9182     test_viewmodify_assign();
9183     test_stringtable();
9184     test_viewmodify_delete();
9185     test_defaultdatabase();
9186     test_order();
9187     test_viewmodify_delete_temporary();
9188     test_deleterow();
9189     test_quotes();
9190     test_carriagereturn();
9191     test_noquotes();
9192     test_forcecodepage();
9193     test_viewmodify_refresh();
9194     test_where_viewmodify();
9195     test_storages_table();
9196     test_dbtopackage();
9197     test_droptable();
9198     test_dbmerge();
9199     test_select_with_tablenames();
9200     test_insertorder();
9201     test_columnorder();
9202     test_suminfo_import();
9203     test_createtable();
9204     test_collation();
9205 }