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