gdiplus: Select the font into the appropriate hdc in GdipMeasureString.
[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     UINT i, test_max, offset, count;
5270     const char *query;
5271     UINT r;
5272
5273     DeleteFile(msifile);
5274
5275     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5276     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5277
5278     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5279     r = run_query( hdb, 0, query );
5280     ok(r == ERROR_SUCCESS, "query failed\n");
5281
5282     query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5283     r = run_query( hdb, 0, query );
5284     ok(r == ERROR_SUCCESS, "query failed\n");
5285
5286     query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5287     r = run_query( hdb, 0, query );
5288     ok(r == ERROR_SUCCESS, "query failed\n");
5289
5290     query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5291     r = run_query( hdb, 0, query );
5292     ok(r == ERROR_SUCCESS, "query failed\n");
5293
5294     query = "SELECT `B` FROM `table`";
5295     r = MsiDatabaseOpenView(hdb, query, &hview);
5296     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5297     r = MsiViewExecute(hview, 0);
5298     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5299     r = MsiViewFetch(hview, &hrec);
5300     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5301
5302     r = MsiRecordSetInteger(hrec, 1, 0);
5303     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5304
5305     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5306     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5307
5308     r = MsiCloseHandle(hrec);
5309     ok(r == ERROR_SUCCESS, "failed to close record\n");
5310
5311     r = MsiViewClose(hview);
5312     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5313     r = MsiCloseHandle(hview);
5314     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5315
5316     query = "SELECT * FROM `table`";
5317     r = MsiDatabaseOpenView(hdb, query, &hview);
5318     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5319     r = MsiViewExecute(hview, 0);
5320     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5321     r = MsiViewFetch(hview, &hrec);
5322     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5323
5324     r = MsiRecordGetInteger(hrec, 1);
5325     ok(r == 1, "Expected 1, got %d\n", r);
5326     r = MsiRecordGetInteger(hrec, 2);
5327     ok(r == 0, "Expected 0, got %d\n", r);
5328
5329     r = MsiCloseHandle(hrec);
5330     ok(r == ERROR_SUCCESS, "failed to close record\n");
5331
5332     r = MsiViewFetch(hview, &hrec);
5333     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5334
5335     r = MsiRecordGetInteger(hrec, 1);
5336     ok(r == 3, "Expected 3, got %d\n", r);
5337     r = MsiRecordGetInteger(hrec, 2);
5338     ok(r == 4, "Expected 4, got %d\n", r);
5339
5340     r = MsiCloseHandle(hrec);
5341     ok(r == ERROR_SUCCESS, "failed to close record\n");
5342
5343     r = MsiViewFetch(hview, &hrec);
5344     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5345
5346     r = MsiRecordGetInteger(hrec, 1);
5347     ok(r == 5, "Expected 5, got %d\n", r);
5348     r = MsiRecordGetInteger(hrec, 2);
5349     ok(r == 6, "Expected 6, got %d\n", r);
5350
5351     r = MsiCloseHandle(hrec);
5352     ok(r == ERROR_SUCCESS, "failed to close record\n");
5353
5354     r = MsiViewFetch(hview, &hrec);
5355     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5356
5357     r = MsiViewClose(hview);
5358     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5359     r = MsiCloseHandle(hview);
5360     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5361
5362     /* loop through all elements */
5363     query = "SELECT `B` FROM `table`";
5364     r = MsiDatabaseOpenView(hdb, query, &hview);
5365     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5366     r = MsiViewExecute(hview, 0);
5367     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5368
5369     while (TRUE)
5370     {
5371         r = MsiViewFetch(hview, &hrec);
5372         if (r != ERROR_SUCCESS)
5373             break;
5374
5375         r = MsiRecordSetInteger(hrec, 1, 0);
5376         ok(r == ERROR_SUCCESS, "failed to set integer\n");
5377
5378         r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5379         ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5380
5381         r = MsiCloseHandle(hrec);
5382         ok(r == ERROR_SUCCESS, "failed to close record\n");
5383     }
5384
5385     r = MsiViewClose(hview);
5386     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5387     r = MsiCloseHandle(hview);
5388     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5389
5390     query = "SELECT * FROM `table`";
5391     r = MsiDatabaseOpenView(hdb, query, &hview);
5392     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5393     r = MsiViewExecute(hview, 0);
5394     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5395     r = MsiViewFetch(hview, &hrec);
5396     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5397
5398     r = MsiRecordGetInteger(hrec, 1);
5399     ok(r == 1, "Expected 1, got %d\n", r);
5400     r = MsiRecordGetInteger(hrec, 2);
5401     ok(r == 0, "Expected 0, got %d\n", r);
5402
5403     r = MsiCloseHandle(hrec);
5404     ok(r == ERROR_SUCCESS, "failed to close record\n");
5405
5406     r = MsiViewFetch(hview, &hrec);
5407     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5408
5409     r = MsiRecordGetInteger(hrec, 1);
5410     ok(r == 3, "Expected 3, got %d\n", r);
5411     r = MsiRecordGetInteger(hrec, 2);
5412     ok(r == 0, "Expected 0, got %d\n", r);
5413
5414     r = MsiCloseHandle(hrec);
5415     ok(r == ERROR_SUCCESS, "failed to close record\n");
5416
5417     r = MsiViewFetch(hview, &hrec);
5418     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5419
5420     r = MsiRecordGetInteger(hrec, 1);
5421     ok(r == 5, "Expected 5, got %d\n", r);
5422     r = MsiRecordGetInteger(hrec, 2);
5423     ok(r == 0, "Expected 0, got %d\n", r);
5424
5425     r = MsiCloseHandle(hrec);
5426     ok(r == ERROR_SUCCESS, "failed to close record\n");
5427
5428     r = MsiViewFetch(hview, &hrec);
5429     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5430
5431     r = MsiViewClose(hview);
5432     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5433     r = MsiCloseHandle(hview);
5434     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5435
5436     query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5437     r = run_query( hdb, 0, query );
5438     ok(r == ERROR_SUCCESS, "query failed\n");
5439
5440     query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5441     r = MsiDatabaseOpenView( hdb, query, &hview );
5442     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5443
5444     test_max = 100;
5445     offset = 1234;
5446     for(i = 0; i < test_max; i++)
5447     {
5448
5449         hrec = MsiCreateRecord( 2 );
5450         MsiRecordSetInteger( hrec, 1, test_max - i );
5451         MsiRecordSetInteger( hrec, 2, i );
5452
5453         r = MsiViewExecute( hview, hrec );
5454         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5455
5456         r = MsiCloseHandle( hrec );
5457         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5458     }
5459
5460     r = MsiViewClose( hview );
5461     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5462     r = MsiCloseHandle( hview );
5463     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5464
5465     /* Update. */
5466     query = "SELECT * FROM `table2` ORDER BY `B`";
5467     r = MsiDatabaseOpenView( hdb, query, &hview);
5468     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5469     r = MsiViewExecute( hview, 0 );
5470     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5471
5472     count = 0;
5473     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5474     {
5475         UINT b = MsiRecordGetInteger( hrec, 2 );
5476
5477         r = MsiRecordSetInteger( hrec, 2, b + offset);
5478         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5479
5480         r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5481         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5482
5483         r = MsiCloseHandle(hrec);
5484         ok(r == ERROR_SUCCESS, "failed to close record\n");
5485         count++;
5486     }
5487     ok(count == test_max, "Got count %d\n", count);
5488
5489     r = MsiViewClose(hview);
5490     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5491     r = MsiCloseHandle(hview);
5492     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5493
5494     /* Recheck. */
5495     query = "SELECT * FROM `table2` ORDER BY `B`";
5496     r = MsiDatabaseOpenView( hdb, query, &hview);
5497     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5498     r = MsiViewExecute( hview, 0 );
5499     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5500
5501     count = 0;
5502     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5503     {
5504         UINT a = MsiRecordGetInteger( hrec, 1 );
5505         UINT b = MsiRecordGetInteger( hrec, 2 );
5506         ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5507             a, b, test_max - a + offset, b);
5508
5509         r = MsiCloseHandle(hrec);
5510         ok(r == ERROR_SUCCESS, "failed to close record\n");
5511         count++;
5512     }
5513     ok(count == test_max, "Got count %d\n", count);
5514
5515     r = MsiViewClose(hview);
5516     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5517     r = MsiCloseHandle(hview);
5518     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5519
5520     r = MsiCloseHandle( hdb );
5521     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5522 }
5523
5524 static void test_viewmodify_assign(void)
5525 {
5526     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5527     const char *query;
5528     UINT r;
5529
5530     /* setup database */
5531     DeleteFile(msifile);
5532
5533     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5534     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5535
5536     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5537     r = run_query( hdb, 0, query );
5538     ok(r == ERROR_SUCCESS, "query failed\n");
5539
5540     /* assign to view, new primary key */
5541     query = "SELECT * FROM `table`";
5542     r = MsiDatabaseOpenView(hdb, query, &hview);
5543     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5544     r = MsiViewExecute(hview, 0);
5545     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5546
5547     hrec = MsiCreateRecord(2);
5548     ok(hrec != 0, "MsiCreateRecord failed\n");
5549
5550     r = MsiRecordSetInteger(hrec, 1, 1);
5551     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5552     r = MsiRecordSetInteger(hrec, 2, 2);
5553     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5554
5555     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5556     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5557
5558     r = MsiCloseHandle(hrec);
5559     ok(r == ERROR_SUCCESS, "failed to close record\n");
5560
5561     r = MsiViewClose(hview);
5562     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5563     r = MsiCloseHandle(hview);
5564     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5565
5566     query = "SELECT * FROM `table`";
5567     r = MsiDatabaseOpenView(hdb, query, &hview);
5568     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5569     r = MsiViewExecute(hview, 0);
5570     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5571     r = MsiViewFetch(hview, &hrec);
5572     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5573
5574     r = MsiRecordGetInteger(hrec, 1);
5575     ok(r == 1, "Expected 1, got %d\n", r);
5576     r = MsiRecordGetInteger(hrec, 2);
5577     ok(r == 2, "Expected 2, got %d\n", r);
5578
5579     r = MsiCloseHandle(hrec);
5580     ok(r == ERROR_SUCCESS, "failed to close record\n");
5581
5582     r = MsiViewFetch(hview, &hrec);
5583     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5584
5585     r = MsiViewClose(hview);
5586     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5587     r = MsiCloseHandle(hview);
5588     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5589
5590     /* assign to view, primary key matches */
5591     query = "SELECT * FROM `table`";
5592     r = MsiDatabaseOpenView(hdb, query, &hview);
5593     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5594     r = MsiViewExecute(hview, 0);
5595     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5596
5597     hrec = MsiCreateRecord(2);
5598     ok(hrec != 0, "MsiCreateRecord failed\n");
5599
5600     r = MsiRecordSetInteger(hrec, 1, 1);
5601     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5602     r = MsiRecordSetInteger(hrec, 2, 4);
5603     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5604
5605     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5606     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5607
5608     r = MsiCloseHandle(hrec);
5609     ok(r == ERROR_SUCCESS, "failed to close record\n");
5610
5611     r = MsiViewClose(hview);
5612     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5613     r = MsiCloseHandle(hview);
5614     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5615
5616     query = "SELECT * FROM `table`";
5617     r = MsiDatabaseOpenView(hdb, query, &hview);
5618     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5619     r = MsiViewExecute(hview, 0);
5620     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5621     r = MsiViewFetch(hview, &hrec);
5622     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5623
5624     r = MsiRecordGetInteger(hrec, 1);
5625     ok(r == 1, "Expected 1, got %d\n", r);
5626     r = MsiRecordGetInteger(hrec, 2);
5627     ok(r == 4, "Expected 4, got %d\n", r);
5628
5629     r = MsiCloseHandle(hrec);
5630     ok(r == ERROR_SUCCESS, "failed to close record\n");
5631
5632     r = MsiViewFetch(hview, &hrec);
5633     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5634
5635     r = MsiViewClose(hview);
5636     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5637     r = MsiCloseHandle(hview);
5638     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5639
5640     /* close database */
5641     r = MsiCloseHandle( hdb );
5642     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5643 }
5644
5645 static const WCHAR data10[] = { /* MOO */
5646     0x8001, 0x000b,
5647 };
5648 static const WCHAR data11[] = { /* AAR */
5649     0x8002, 0x8005,
5650     0x000c, 0x000f,
5651 };
5652 static const char data12[] = /* _StringData */
5653     "MOOABAARCDonetwofourfive";
5654 static const WCHAR data13[] = { /* _StringPool */
5655 /*  len, refs */
5656     0,   0,    /* string 0 ''     */
5657     0,   0,    /* string 1 ''     */
5658     0,   0,    /* string 2 ''     */
5659     0,   0,    /* string 3 ''     */
5660     0,   0,    /* string 4 ''     */
5661     3,   3,    /* string 5 'MOO'  */
5662     1,   1,    /* string 6 'A'    */
5663     1,   1,    /* string 7 'B'    */
5664     3,   3,    /* string 8 'AAR'  */
5665     1,   1,    /* string 9 'C'    */
5666     1,   1,    /* string a 'D'    */
5667     3,   1,    /* string b 'one'  */
5668     3,   1,    /* string c 'two'  */
5669     0,   0,    /* string d ''     */
5670     4,   1,    /* string e 'four' */
5671     4,   1,    /* string f 'five' */
5672 };
5673
5674 static void test_stringtable(void)
5675 {
5676     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5677     IStorage *stg = NULL;
5678     IStream *stm;
5679     WCHAR name[0x20];
5680     HRESULT hr;
5681     const char *query;
5682     char buffer[MAX_PATH];
5683     WCHAR data[MAX_PATH];
5684     DWORD sz, read;
5685     UINT r;
5686
5687     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5688     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5689     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5690     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5691     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5692
5693     DeleteFile(msifile);
5694
5695     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5697
5698     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5699     r = run_query(hdb, 0, query);
5700     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5701
5702     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5703     r = run_query(hdb, 0, query);
5704     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5705
5706     /* insert persistent row */
5707     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5708     r = run_query(hdb, 0, query);
5709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5710
5711     /* insert persistent row */
5712     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5713     r = run_query(hdb, 0, query);
5714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5715
5716     /* open a view */
5717     query = "SELECT * FROM `MOO`";
5718     r = MsiDatabaseOpenView(hdb, query, &hview);
5719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5720     r = MsiViewExecute(hview, 0);
5721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5722
5723     hrec = MsiCreateRecord(2);
5724
5725     r = MsiRecordSetInteger(hrec, 1, 3);
5726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5727     r = MsiRecordSetString(hrec, 2, "three");
5728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5729
5730     /* insert a nonpersistent row */
5731     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5732     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5733
5734     r = MsiCloseHandle(hrec);
5735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5736     r = MsiViewClose(hview);
5737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5738     r = MsiCloseHandle(hview);
5739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5740
5741     /* insert persistent row */
5742     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5743     r = run_query(hdb, 0, query);
5744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5745
5746     /* insert persistent row */
5747     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5748     r = run_query(hdb, 0, query);
5749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5750
5751     r = MsiDatabaseCommit(hdb);
5752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5753
5754     r = MsiCloseHandle(hdb);
5755     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5756
5757     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
5758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5759
5760     query = "SELECT * FROM `MOO`";
5761     r = MsiDatabaseOpenView(hdb, query, &hview);
5762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5763
5764     r = MsiViewExecute(hview, 0);
5765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5766
5767     r = MsiViewFetch(hview, &hrec);
5768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5769
5770     r = MsiRecordGetFieldCount(hrec);
5771     ok(r == 2, "Expected 2, got %d\n", r);
5772
5773     r = MsiRecordGetInteger(hrec, 1);
5774     ok(r == 1, "Expected 1, got %d\n", r);
5775
5776     sz = sizeof(buffer);
5777     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5778     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5779     ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
5780
5781     r = MsiCloseHandle(hrec);
5782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5783
5784     r = MsiViewFetch(hview, &hrec);
5785     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5786
5787     r = MsiViewClose(hview);
5788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5789     r = MsiCloseHandle(hview);
5790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5791     r = MsiCloseHandle(hrec);
5792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5793
5794     query = "SELECT * FROM `AAR`";
5795     r = MsiDatabaseOpenView(hdb, query, &hview);
5796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5797
5798     r = MsiViewExecute(hview, 0);
5799     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5800
5801     r = MsiViewFetch(hview, &hrec);
5802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5803
5804     r = MsiRecordGetFieldCount(hrec);
5805     ok(r == 2, "Expected 2, got %d\n", r);
5806
5807     r = MsiRecordGetInteger(hrec, 1);
5808     ok(r == 2, "Expected 2, got %d\n", r);
5809
5810     sz = sizeof(buffer);
5811     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5813     ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
5814
5815     r = MsiCloseHandle(hrec);
5816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5817
5818     r = MsiViewFetch(hview, &hrec);
5819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5820
5821     r = MsiRecordGetFieldCount(hrec);
5822     ok(r == 2, "Expected 2, got %d\n", r);
5823
5824     r = MsiRecordGetInteger(hrec, 1);
5825     ok(r == 5, "Expected 5, got %d\n", r);
5826
5827     sz = sizeof(buffer);
5828     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5830     ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
5831
5832     r = MsiCloseHandle(hrec);
5833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5834
5835     r = MsiViewFetch(hview, &hrec);
5836     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5837
5838     r = MsiViewClose(hview);
5839     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5840     r = MsiCloseHandle(hview);
5841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5842     r = MsiCloseHandle(hrec);
5843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5844     r = MsiCloseHandle(hdb);
5845     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5846
5847     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5848     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5849     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5850     ok(stg != NULL, "Expected non-NULL storage\n");
5851
5852     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5853     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5854     ok(stm != NULL, "Expected non-NULL stream\n");
5855
5856     hr = IStream_Read(stm, data, MAX_PATH, &read);
5857     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5858     ok(read == 4, "Expected 4, got %d\n", read);
5859     todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5860
5861     hr = IStream_Release(stm);
5862     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5863
5864     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5865     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5866     ok(stm != NULL, "Expected non-NULL stream\n");
5867
5868     hr = IStream_Read(stm, data, MAX_PATH, &read);
5869     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5870     ok(read == 8, "Expected 8, got %d\n", read);
5871     todo_wine
5872     {
5873         ok(!memcmp(data, data11, read), "Unexpected data\n");
5874     }
5875
5876     hr = IStream_Release(stm);
5877     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5878
5879     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5880     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5881     ok(stm != NULL, "Expected non-NULL stream\n");
5882
5883     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5884     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5885     ok(read == 24, "Expected 24, got %d\n", read);
5886     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5887
5888     hr = IStream_Release(stm);
5889     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5890
5891     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5892     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5893     ok(stm != NULL, "Expected non-NULL stream\n");
5894
5895     hr = IStream_Read(stm, data, MAX_PATH, &read);
5896     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5897     todo_wine
5898     {
5899         ok(read == 64, "Expected 64, got %d\n", read);
5900         ok(!memcmp(data, data13, read), "Unexpected data\n");
5901     }
5902
5903     hr = IStream_Release(stm);
5904     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5905
5906     hr = IStorage_Release(stg);
5907     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5908
5909     DeleteFileA(msifile);
5910 }
5911
5912 static void test_viewmodify_delete(void)
5913 {
5914     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5915     UINT r;
5916     const char *query;
5917     char buffer[0x100];
5918     DWORD sz;
5919
5920     DeleteFile(msifile);
5921
5922     /* just MsiOpenDatabase should not create a file */
5923     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
5924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5925
5926     query = "CREATE TABLE `phone` ( "
5927             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
5928             "PRIMARY KEY `id`)";
5929     r = run_query(hdb, 0, query);
5930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5931
5932     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5933         "VALUES('1', 'Alan', '5030581')";
5934     r = run_query(hdb, 0, query);
5935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5936
5937     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5938         "VALUES('2', 'Barry', '928440')";
5939     r = run_query(hdb, 0, query);
5940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5941
5942     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5943         "VALUES('3', 'Cindy', '2937550')";
5944     r = run_query(hdb, 0, query);
5945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5946
5947     query = "SELECT * FROM `phone` WHERE `id` <= 2";
5948     r = MsiDatabaseOpenView(hdb, query, &hview);
5949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5950     r = MsiViewExecute(hview, 0);
5951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5952     r = MsiViewFetch(hview, &hrec);
5953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5954
5955     /* delete 1 */
5956     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5958
5959     r = MsiCloseHandle(hrec);
5960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5961     r = MsiViewFetch(hview, &hrec);
5962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5963
5964     /* delete 2 */
5965     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5967
5968     r = MsiCloseHandle(hrec);
5969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5970     r = MsiViewClose(hview);
5971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5972     r = MsiCloseHandle(hview);
5973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5974
5975     query = "SELECT * FROM `phone`";
5976     r = MsiDatabaseOpenView(hdb, query, &hview);
5977     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5978     r = MsiViewExecute(hview, 0);
5979     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5980     r = MsiViewFetch(hview, &hrec);
5981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5982
5983     r = MsiRecordGetInteger(hrec, 1);
5984     ok(r == 3, "Expected 3, got %d\n", r);
5985
5986     sz = sizeof(buffer);
5987     r = MsiRecordGetString(hrec, 2, buffer, &sz);
5988     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5989     ok(!lstrcmp(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
5990
5991     sz = sizeof(buffer);
5992     r = MsiRecordGetString(hrec, 3, buffer, &sz);
5993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5994     ok(!lstrcmp(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
5995
5996     r = MsiCloseHandle(hrec);
5997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5998
5999     r = MsiViewFetch(hview, &hrec);
6000     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6001
6002     r = MsiViewClose(hview);
6003     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6004     r = MsiCloseHandle(hview);
6005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6006     r = MsiCloseHandle(hdb);
6007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6008 }
6009
6010 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
6011 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
6012 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
6013
6014 static const WCHAR data14[] = { /* _StringPool */
6015 /*  len, refs */
6016     0,   0,    /* string 0 ''    */
6017 };
6018
6019 static const struct {
6020     LPCWSTR name;
6021     const void *data;
6022     DWORD size;
6023 } database_table_data[] =
6024 {
6025     {_Tables, NULL, 0},
6026     {_StringData, NULL, 0},
6027     {_StringPool, data14, sizeof data14},
6028 };
6029
6030 static void enum_stream_names(IStorage *stg)
6031 {
6032     IEnumSTATSTG *stgenum = NULL;
6033     IStream *stm;
6034     HRESULT hr;
6035     STATSTG stat;
6036     ULONG n, count;
6037     BYTE data[MAX_PATH];
6038     BYTE check[MAX_PATH];
6039     DWORD sz;
6040
6041     memset(check, 'a', MAX_PATH);
6042
6043     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
6044     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6045
6046     n = 0;
6047     while(TRUE)
6048     {
6049         count = 0;
6050         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
6051         if(FAILED(hr) || !count)
6052             break;
6053
6054         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
6055            "Expected table %d name to match\n", n);
6056
6057         stm = NULL;
6058         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
6059                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6060         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6061         ok(stm != NULL, "Expected non-NULL stream\n");
6062
6063         CoTaskMemFree(stat.pwcsName);
6064
6065         sz = MAX_PATH;
6066         memset(data, 'a', MAX_PATH);
6067         hr = IStream_Read(stm, data, sz, &count);
6068         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6069
6070         ok(count == database_table_data[n].size,
6071            "Expected %d, got %d\n", database_table_data[n].size, count);
6072
6073         if (!database_table_data[n].size)
6074             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
6075         else
6076             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
6077                "Expected table %d data to match\n", n);
6078
6079         IStream_Release(stm);
6080         n++;
6081     }
6082
6083     ok(n == 3, "Expected 3, got %d\n", n);
6084
6085     IEnumSTATSTG_Release(stgenum);
6086 }
6087
6088 static void test_defaultdatabase(void)
6089 {
6090     UINT r;
6091     HRESULT hr;
6092     MSIHANDLE hdb;
6093     IStorage *stg = NULL;
6094
6095     DeleteFile(msifile);
6096
6097     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6099
6100     r = MsiDatabaseCommit(hdb);
6101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6102
6103     MsiCloseHandle(hdb);
6104
6105     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6106     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6107     ok(stg != NULL, "Expected non-NULL stg\n");
6108
6109     enum_stream_names(stg);
6110
6111     IStorage_Release(stg);
6112     DeleteFileA(msifile);
6113 }
6114
6115 static void test_order(void)
6116 {
6117     MSIHANDLE hdb, hview, hrec;
6118     CHAR buffer[MAX_PATH];
6119     LPCSTR query;
6120     UINT r, sz;
6121     int val;
6122
6123     hdb = create_db();
6124     ok(hdb, "failed to create db\n");
6125
6126     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6127     r = run_query(hdb, 0, query);
6128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6129
6130     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6131     r = run_query(hdb, 0, query);
6132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6133
6134     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6135     r = run_query(hdb, 0, query);
6136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6137
6138     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6139     r = run_query(hdb, 0, query);
6140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6141
6142     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6143     r = run_query(hdb, 0, query);
6144     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6145
6146     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6147     r = run_query(hdb, 0, query);
6148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6149
6150     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6151     r = run_query(hdb, 0, query);
6152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6153
6154     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6155     r = run_query(hdb, 0, query);
6156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6157
6158     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6159     r = run_query(hdb, 0, query);
6160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6161
6162     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6163     r = MsiDatabaseOpenView(hdb, query, &hview);
6164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6165     r = MsiViewExecute(hview, 0);
6166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6167
6168     r = MsiViewFetch(hview, &hrec);
6169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6170
6171     val = MsiRecordGetInteger(hrec, 1);
6172     ok(val == 3, "Expected 3, got %d\n", val);
6173
6174     val = MsiRecordGetInteger(hrec, 2);
6175     ok(val == 4, "Expected 3, got %d\n", val);
6176
6177     MsiCloseHandle(hrec);
6178
6179     r = MsiViewFetch(hview, &hrec);
6180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6181
6182     val = MsiRecordGetInteger(hrec, 1);
6183     ok(val == 5, "Expected 5, got %d\n", val);
6184
6185     val = MsiRecordGetInteger(hrec, 2);
6186     ok(val == 6, "Expected 6, got %d\n", val);
6187
6188     MsiCloseHandle(hrec);
6189
6190     r = MsiViewFetch(hview, &hrec);
6191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6192
6193     val = MsiRecordGetInteger(hrec, 1);
6194     ok(val == 1, "Expected 1, got %d\n", val);
6195
6196     val = MsiRecordGetInteger(hrec, 2);
6197     ok(val == 2, "Expected 2, got %d\n", val);
6198
6199     MsiCloseHandle(hrec);
6200
6201     r = MsiViewFetch(hview, &hrec);
6202     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6203
6204     MsiViewClose(hview);
6205     MsiCloseHandle(hview);
6206
6207     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6208     r = MsiDatabaseOpenView(hdb, query, &hview);
6209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6210     r = MsiViewExecute(hview, 0);
6211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6212
6213     r = MsiViewFetch(hview, &hrec);
6214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6215
6216     val = MsiRecordGetInteger(hrec, 1);
6217     ok(val == 1, "Expected 1, got %d\n", val);
6218
6219     val = MsiRecordGetInteger(hrec, 2);
6220     ok(val == 12, "Expected 12, got %d\n", val);
6221
6222     MsiCloseHandle(hrec);
6223
6224     r = MsiViewFetch(hview, &hrec);
6225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6226
6227     val = MsiRecordGetInteger(hrec, 1);
6228     ok(val == 3, "Expected 3, got %d\n", val);
6229
6230     val = MsiRecordGetInteger(hrec, 2);
6231     ok(val == 12, "Expected 12, got %d\n", val);
6232
6233     MsiCloseHandle(hrec);
6234
6235     r = MsiViewFetch(hview, &hrec);
6236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6237
6238     val = MsiRecordGetInteger(hrec, 1);
6239     ok(val == 5, "Expected 5, got %d\n", val);
6240
6241     val = MsiRecordGetInteger(hrec, 2);
6242     ok(val == 12, "Expected 12, got %d\n", val);
6243
6244     MsiCloseHandle(hrec);
6245
6246     r = MsiViewFetch(hview, &hrec);
6247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6248
6249     val = MsiRecordGetInteger(hrec, 1);
6250     ok(val == 1, "Expected 1, got %d\n", val);
6251
6252     val = MsiRecordGetInteger(hrec, 2);
6253     ok(val == 14, "Expected 14, got %d\n", val);
6254
6255     MsiCloseHandle(hrec);
6256
6257     r = MsiViewFetch(hview, &hrec);
6258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6259
6260     val = MsiRecordGetInteger(hrec, 1);
6261     ok(val == 3, "Expected 3, got %d\n", val);
6262
6263     val = MsiRecordGetInteger(hrec, 2);
6264     ok(val == 14, "Expected 14, got %d\n", val);
6265
6266     MsiCloseHandle(hrec);
6267
6268     r = MsiViewFetch(hview, &hrec);
6269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6270
6271     val = MsiRecordGetInteger(hrec, 1);
6272     ok(val == 5, "Expected 5, got %d\n", val);
6273
6274     val = MsiRecordGetInteger(hrec, 2);
6275     ok(val == 14, "Expected 14, got %d\n", val);
6276
6277     MsiCloseHandle(hrec);
6278
6279     r = MsiViewFetch(hview, &hrec);
6280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6281
6282     val = MsiRecordGetInteger(hrec, 1);
6283     ok(val == 1, "Expected 1, got %d\n", val);
6284
6285     val = MsiRecordGetInteger(hrec, 2);
6286     ok(val == 10, "Expected 10, got %d\n", val);
6287
6288     MsiCloseHandle(hrec);
6289
6290     r = MsiViewFetch(hview, &hrec);
6291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6292
6293     val = MsiRecordGetInteger(hrec, 1);
6294     ok(val == 3, "Expected 3, got %d\n", val);
6295
6296     val = MsiRecordGetInteger(hrec, 2);
6297     ok(val == 10, "Expected 10, got %d\n", val);
6298
6299     MsiCloseHandle(hrec);
6300
6301     r = MsiViewFetch(hview, &hrec);
6302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6303
6304     val = MsiRecordGetInteger(hrec, 1);
6305     ok(val == 5, "Expected 5, got %d\n", val);
6306
6307     val = MsiRecordGetInteger(hrec, 2);
6308     ok(val == 10, "Expected 10, got %d\n", val);
6309
6310     MsiCloseHandle(hrec);
6311
6312     r = MsiViewFetch(hview, &hrec);
6313     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6314
6315     MsiViewClose(hview);
6316     MsiCloseHandle(hview);
6317
6318     query = "SELECT * FROM `Empty` ORDER BY `A`";
6319     r = MsiDatabaseOpenView(hdb, query, &hview);
6320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6321     r = MsiViewExecute(hview, 0);
6322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6323
6324     r = MsiViewFetch(hview, &hrec);
6325     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6326
6327     MsiViewClose(hview);
6328     MsiCloseHandle(hview);
6329
6330     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6331     r = run_query(hdb, 0, query);
6332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6333
6334     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6335     r = run_query(hdb, 0, query);
6336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6337
6338     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6339     r = run_query(hdb, 0, query);
6340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6341
6342     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6343     r = run_query(hdb, 0, query);
6344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6345
6346     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6347     r = MsiDatabaseOpenView(hdb, query, &hview);
6348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6349     r = MsiViewExecute(hview, 0);
6350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6351
6352     r = MsiViewFetch(hview, &hrec);
6353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6354
6355     sz = sizeof(buffer);
6356     r = MsiRecordGetString(hrec, 1, buffer, &sz);
6357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6358     ok(!lstrcmp(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6359
6360     r = MsiRecordGetInteger(hrec, 2);
6361     ok(r == 3, "Expected 3, got %d\n", r);
6362
6363     MsiCloseHandle(hrec);
6364
6365     r = MsiViewFetch(hview, &hrec);
6366     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6367
6368     MsiViewClose(hview);
6369     MsiCloseHandle(hview);
6370     MsiCloseHandle(hdb);
6371 }
6372
6373 static void test_viewmodify_delete_temporary(void)
6374 {
6375     MSIHANDLE hdb, hview, hrec;
6376     const char *query;
6377     UINT r;
6378
6379     DeleteFile(msifile);
6380
6381     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6383
6384     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6385     r = run_query(hdb, 0, query);
6386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6387
6388     query = "SELECT * FROM `Table`";
6389     r = MsiDatabaseOpenView(hdb, query, &hview);
6390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6391     r = MsiViewExecute(hview, 0);
6392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6393
6394     hrec = MsiCreateRecord(1);
6395     MsiRecordSetInteger(hrec, 1, 1);
6396
6397     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6399
6400     MsiCloseHandle(hrec);
6401
6402     hrec = MsiCreateRecord(1);
6403     MsiRecordSetInteger(hrec, 1, 2);
6404
6405     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407
6408     MsiCloseHandle(hrec);
6409
6410     hrec = MsiCreateRecord(1);
6411     MsiRecordSetInteger(hrec, 1, 3);
6412
6413     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6415
6416     MsiCloseHandle(hrec);
6417
6418     hrec = MsiCreateRecord(1);
6419     MsiRecordSetInteger(hrec, 1, 4);
6420
6421     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6423
6424     MsiCloseHandle(hrec);
6425     MsiViewClose(hview);
6426     MsiCloseHandle(hview);
6427
6428     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6429     r = MsiDatabaseOpenView(hdb, query, &hview);
6430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6431     r = MsiViewExecute(hview, 0);
6432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6433     r = MsiViewFetch(hview, &hrec);
6434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6435
6436     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6438
6439     MsiCloseHandle(hrec);
6440     MsiViewClose(hview);
6441     MsiCloseHandle(hview);
6442
6443     query = "SELECT * FROM `Table` WHERE  `A` = 3";
6444     r = MsiDatabaseOpenView(hdb, query, &hview);
6445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6446     r = MsiViewExecute(hview, 0);
6447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6448     r = MsiViewFetch(hview, &hrec);
6449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6450
6451     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6453
6454     MsiCloseHandle(hrec);
6455     MsiViewClose(hview);
6456     MsiCloseHandle(hview);
6457
6458     query = "SELECT * FROM `Table` ORDER BY `A`";
6459     r = MsiDatabaseOpenView(hdb, query, &hview);
6460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6461     r = MsiViewExecute(hview, 0);
6462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6463
6464     r = MsiViewFetch(hview, &hrec);
6465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6466
6467     r = MsiRecordGetInteger(hrec, 1);
6468     ok(r == 1, "Expected 1, got %d\n", r);
6469
6470     MsiCloseHandle(hrec);
6471
6472     r = MsiViewFetch(hview, &hrec);
6473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6474
6475     r = MsiRecordGetInteger(hrec, 1);
6476     ok(r == 4, "Expected 4, got %d\n", r);
6477
6478     MsiCloseHandle(hrec);
6479
6480     r = MsiViewFetch(hview, &hrec);
6481     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6482
6483     MsiViewClose(hview);
6484     MsiCloseHandle(hview);
6485     MsiCloseHandle(hdb);
6486     DeleteFileA(msifile);
6487 }
6488
6489 static void test_deleterow(void)
6490 {
6491     MSIHANDLE hdb, hview, hrec;
6492     const char *query;
6493     char buf[MAX_PATH];
6494     UINT r;
6495     DWORD size;
6496
6497     DeleteFile(msifile);
6498
6499     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6501
6502     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6503     r = run_query(hdb, 0, query);
6504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6505
6506     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6507     r = run_query(hdb, 0, query);
6508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6509
6510     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6511     r = run_query(hdb, 0, query);
6512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6513
6514     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6515     r = run_query(hdb, 0, query);
6516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6517
6518     r = MsiDatabaseCommit(hdb);
6519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6520
6521     MsiCloseHandle(hdb);
6522
6523     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
6524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6525
6526     query = "SELECT * FROM `Table`";
6527     r = MsiDatabaseOpenView(hdb, query, &hview);
6528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6529     r = MsiViewExecute(hview, 0);
6530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6531
6532     r = MsiViewFetch(hview, &hrec);
6533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6534
6535     size = MAX_PATH;
6536     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6538     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6539
6540     MsiCloseHandle(hrec);
6541
6542     r = MsiViewFetch(hview, &hrec);
6543     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6544
6545     MsiViewClose(hview);
6546     MsiCloseHandle(hview);
6547     MsiCloseHandle(hdb);
6548     DeleteFileA(msifile);
6549 }
6550
6551 static const CHAR import_dat[] = "A\n"
6552                                  "s72\n"
6553                                  "Table\tA\n"
6554                                  "This is a new 'string' ok\n";
6555
6556 static void test_quotes(void)
6557 {
6558     MSIHANDLE hdb, hview, hrec;
6559     const char *query;
6560     char buf[MAX_PATH];
6561     UINT r;
6562     DWORD size;
6563
6564     DeleteFile(msifile);
6565
6566     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6567     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6568
6569     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6570     r = run_query(hdb, 0, query);
6571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6572
6573     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6574     r = run_query(hdb, 0, query);
6575     ok(r == ERROR_BAD_QUERY_SYNTAX,
6576        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6577
6578     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6579     r = run_query(hdb, 0, query);
6580     ok(r == ERROR_BAD_QUERY_SYNTAX,
6581        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6582
6583     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6584     r = run_query(hdb, 0, query);
6585     ok(r == ERROR_BAD_QUERY_SYNTAX,
6586        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6587
6588     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6589     r = run_query(hdb, 0, query);
6590     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6591
6592     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6593     r = run_query(hdb, 0, query);
6594     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6595
6596     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6597     r = run_query(hdb, 0, query);
6598     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6599
6600     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6601     r = run_query(hdb, 0, query);
6602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6603
6604     query = "SELECT * FROM `Table`";
6605     r = MsiDatabaseOpenView(hdb, query, &hview);
6606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6607
6608     r = MsiViewExecute(hview, 0);
6609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6610
6611     r = MsiViewFetch(hview, &hrec);
6612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6613
6614     size = MAX_PATH;
6615     r = MsiRecordGetString(hrec, 1, buf, &size);
6616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6617     ok(!lstrcmp(buf, "This is a \"string\" ok"),
6618        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6619
6620     MsiCloseHandle(hrec);
6621
6622     r = MsiViewFetch(hview, &hrec);
6623     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6624
6625     MsiViewClose(hview);
6626     MsiCloseHandle(hview);
6627
6628     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6629
6630     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6632
6633     DeleteFileA("import.idt");
6634
6635     query = "SELECT * FROM `Table`";
6636     r = MsiDatabaseOpenView(hdb, query, &hview);
6637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6638
6639     r = MsiViewExecute(hview, 0);
6640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6641
6642     r = MsiViewFetch(hview, &hrec);
6643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6644
6645     size = MAX_PATH;
6646     r = MsiRecordGetString(hrec, 1, buf, &size);
6647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6648     ok(!lstrcmp(buf, "This is a new 'string' ok"),
6649        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6650
6651     MsiCloseHandle(hrec);
6652
6653     r = MsiViewFetch(hview, &hrec);
6654     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6655
6656     MsiViewClose(hview);
6657     MsiCloseHandle(hview);
6658     MsiCloseHandle(hdb);
6659     DeleteFileA(msifile);
6660 }
6661
6662 static void test_carriagereturn(void)
6663 {
6664     MSIHANDLE hdb, hview, hrec;
6665     const char *query;
6666     char buf[MAX_PATH];
6667     UINT r;
6668     DWORD size;
6669
6670     DeleteFile(msifile);
6671
6672     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6674
6675     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6676     r = run_query(hdb, 0, query);
6677     ok(r == ERROR_BAD_QUERY_SYNTAX,
6678        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6679
6680     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6681     r = run_query(hdb, 0, query);
6682     ok(r == ERROR_BAD_QUERY_SYNTAX,
6683        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6684
6685     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6686     r = run_query(hdb, 0, query);
6687     ok(r == ERROR_BAD_QUERY_SYNTAX,
6688        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6689
6690     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6691     r = run_query(hdb, 0, query);
6692     ok(r == ERROR_BAD_QUERY_SYNTAX,
6693        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6694
6695     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6696     r = run_query(hdb, 0, query);
6697     ok(r == ERROR_BAD_QUERY_SYNTAX,
6698        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6699
6700     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6701     r = run_query(hdb, 0, query);
6702     ok(r == ERROR_BAD_QUERY_SYNTAX,
6703        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6704
6705     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6706     r = run_query(hdb, 0, query);
6707     ok(r == ERROR_BAD_QUERY_SYNTAX,
6708        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6709
6710     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6711     r = run_query(hdb, 0, query);
6712     ok(r == ERROR_BAD_QUERY_SYNTAX,
6713        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6714
6715     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6716     r = run_query(hdb, 0, query);
6717     ok(r == ERROR_BAD_QUERY_SYNTAX,
6718        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6719
6720     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6721     r = run_query(hdb, 0, query);
6722     ok(r == ERROR_BAD_QUERY_SYNTAX,
6723        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6724
6725     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6726     r = run_query(hdb, 0, query);
6727     ok(r == ERROR_BAD_QUERY_SYNTAX,
6728        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6729
6730     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6731     r = run_query(hdb, 0, query);
6732     ok(r == ERROR_BAD_QUERY_SYNTAX,
6733        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6734
6735     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6736     r = run_query(hdb, 0, query);
6737     ok(r == ERROR_BAD_QUERY_SYNTAX,
6738        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6739
6740     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6741     r = run_query(hdb, 0, query);
6742     ok(r == ERROR_BAD_QUERY_SYNTAX,
6743        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6744
6745     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6746     r = run_query(hdb, 0, query);
6747     ok(r == ERROR_BAD_QUERY_SYNTAX,
6748        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6749
6750     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6751     r = run_query(hdb, 0, query);
6752     ok(r == ERROR_BAD_QUERY_SYNTAX,
6753        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6754
6755     query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6756     r = run_query(hdb, 0, query);
6757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6758
6759     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6760     r = run_query(hdb, 0, query);
6761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6762
6763     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6764     r = run_query(hdb, 0, query);
6765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6766
6767     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6768     r = run_query(hdb, 0, query);
6769     ok(r == ERROR_BAD_QUERY_SYNTAX,
6770        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6771
6772     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6773     r = run_query(hdb, 0, query);
6774     ok(r == ERROR_BAD_QUERY_SYNTAX,
6775        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6776
6777     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6778     r = run_query(hdb, 0, query);
6779     ok(r == ERROR_BAD_QUERY_SYNTAX,
6780        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6781
6782     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6783     r = run_query(hdb, 0, query);
6784     ok(r == ERROR_BAD_QUERY_SYNTAX,
6785        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6786
6787     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6788     r = run_query(hdb, 0, query);
6789     ok(r == ERROR_BAD_QUERY_SYNTAX,
6790        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6791
6792     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6793     r = run_query(hdb, 0, query);
6794     ok(r == ERROR_BAD_QUERY_SYNTAX,
6795        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6796
6797     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6798     r = run_query(hdb, 0, query);
6799     ok(r == ERROR_BAD_QUERY_SYNTAX,
6800        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6801
6802     query = "SELECT * FROM `_Tables`";
6803     r = MsiDatabaseOpenView(hdb, query, &hview);
6804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6805     r = MsiViewExecute(hview, 0);
6806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
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, "\rOne"), "Expected \"\\rOne\", 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, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6825
6826     MsiCloseHandle(hrec);
6827
6828     r = MsiViewFetch(hview, &hrec);
6829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6830
6831     size = MAX_PATH;
6832     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6834     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6835
6836     MsiCloseHandle(hrec);
6837
6838     r = MsiViewFetch(hview, &hrec);
6839     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6840
6841     MsiViewClose(hview);
6842     MsiCloseHandle(hview);
6843
6844     MsiCloseHandle(hdb);
6845     DeleteFileA(msifile);
6846 }
6847
6848 static void test_noquotes(void)
6849 {
6850     MSIHANDLE hdb, hview, hrec;
6851     const char *query;
6852     char buf[MAX_PATH];
6853     UINT r;
6854     DWORD size;
6855
6856     DeleteFile(msifile);
6857
6858     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
6859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6860
6861     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6862     r = run_query(hdb, 0, query);
6863     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6864
6865     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6866     r = run_query(hdb, 0, query);
6867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6868
6869     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6870     r = run_query(hdb, 0, query);
6871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6872
6873     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6874     r = run_query(hdb, 0, query);
6875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6876
6877     query = "SELECT * FROM `_Tables`";
6878     r = MsiDatabaseOpenView(hdb, query, &hview);
6879     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6880     r = MsiViewExecute(hview, 0);
6881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6882
6883     r = MsiViewFetch(hview, &hrec);
6884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6885
6886     size = MAX_PATH;
6887     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6889     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6890
6891     MsiCloseHandle(hrec);
6892
6893     r = MsiViewFetch(hview, &hrec);
6894     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6895
6896     size = MAX_PATH;
6897     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6899     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6900
6901     MsiCloseHandle(hrec);
6902
6903     r = MsiViewFetch(hview, &hrec);
6904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6905
6906     size = MAX_PATH;
6907     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6910
6911     MsiCloseHandle(hrec);
6912
6913     r = MsiViewFetch(hview, &hrec);
6914     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6915
6916     MsiViewClose(hview);
6917     MsiCloseHandle(hview);
6918
6919     query = "SELECT * FROM `_Columns`";
6920     r = MsiDatabaseOpenView(hdb, query, &hview);
6921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6922     r = MsiViewExecute(hview, 0);
6923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6924
6925     r = MsiViewFetch(hview, &hrec);
6926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6927
6928     size = MAX_PATH;
6929     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6931     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6932
6933     r = MsiRecordGetInteger(hrec, 2);
6934     ok(r == 1, "Expected 1, got %d\n", r);
6935
6936     size = MAX_PATH;
6937     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6939     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6940
6941     MsiCloseHandle(hrec);
6942
6943     r = MsiViewFetch(hview, &hrec);
6944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6945
6946     size = MAX_PATH;
6947     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6949     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6950
6951     r = MsiRecordGetInteger(hrec, 2);
6952     ok(r == 1, "Expected 1, got %d\n", r);
6953
6954     size = MAX_PATH;
6955     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6957     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6958
6959     MsiCloseHandle(hrec);
6960
6961     r = MsiViewFetch(hview, &hrec);
6962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6963
6964     size = MAX_PATH;
6965     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6967     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
6968
6969     r = MsiRecordGetInteger(hrec, 2);
6970     ok(r == 1, "Expected 1, got %d\n", r);
6971
6972     size = MAX_PATH;
6973     r = MsiRecordGetStringA(hrec, 3, buf, &size);
6974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6975     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
6976
6977     MsiCloseHandle(hrec);
6978
6979     r = MsiViewFetch(hview, &hrec);
6980     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6981
6982     MsiViewClose(hview);
6983     MsiCloseHandle(hview);
6984
6985     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
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 = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
6990     r = run_query(hdb, 0, query);
6991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6992
6993     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
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     query = "SELECT * FROM Table WHERE `A` = 'hi'";
6998     r = run_query(hdb, 0, query);
6999     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7000
7001     query = "SELECT * FROM `Table` WHERE `A` = hi";
7002     r = run_query(hdb, 0, query);
7003     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7004
7005     query = "SELECT * FROM Table";
7006     r = run_query(hdb, 0, query);
7007     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7008
7009     query = "SELECT * FROM Table2";
7010     r = MsiDatabaseOpenView(hdb, query, &hview);
7011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7012     r = MsiViewExecute(hview, 0);
7013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7014
7015     r = MsiViewFetch(hview, &hrec);
7016     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7017
7018     MsiViewClose(hview);
7019     MsiCloseHandle(hview);
7020
7021     query = "SELECT * FROM `Table` WHERE A = 'hi'";
7022     r = MsiDatabaseOpenView(hdb, query, &hview);
7023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7024     r = MsiViewExecute(hview, 0);
7025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7026
7027     r = MsiViewFetch(hview, &hrec);
7028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7029
7030     size = MAX_PATH;
7031     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7033     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7034
7035     MsiCloseHandle(hrec);
7036
7037     r = MsiViewFetch(hview, &hrec);
7038     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7039
7040     MsiViewClose(hview);
7041     MsiCloseHandle(hview);
7042     MsiCloseHandle(hdb);
7043     DeleteFileA(msifile);
7044 }
7045
7046 static void read_file_data(LPCSTR filename, LPSTR buffer)
7047 {
7048     HANDLE file;
7049     DWORD read;
7050
7051     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
7052     ZeroMemory(buffer, MAX_PATH);
7053     ReadFile(file, buffer, MAX_PATH, &read, NULL);
7054     CloseHandle(file);
7055 }
7056
7057 static void test_forcecodepage(void)
7058 {
7059     MSIHANDLE hdb;
7060     const char *query;
7061     char buffer[MAX_PATH];
7062     UINT r;
7063
7064     DeleteFile(msifile);
7065     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
7066
7067     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7069
7070     query = "SELECT * FROM `_ForceCodepage`";
7071     r = run_query(hdb, 0, query);
7072     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7073
7074     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7075     r = run_query(hdb, 0, query);
7076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7077
7078     query = "SELECT * FROM `_ForceCodepage`";
7079     r = run_query(hdb, 0, query);
7080     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7081
7082     r = MsiDatabaseCommit(hdb);
7083     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7084
7085     query = "SELECT * FROM `_ForceCodepage`";
7086     r = run_query(hdb, 0, query);
7087     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7088
7089     MsiCloseHandle(hdb);
7090
7091     r = MsiOpenDatabase(msifile, MSIDBOPEN_DIRECT, &hdb);
7092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7093
7094     query = "SELECT * FROM `_ForceCodepage`";
7095     r = run_query(hdb, 0, query);
7096     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7097
7098     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7099     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7100
7101     read_file_data("forcecodepage.idt", buffer);
7102     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7103        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7104
7105     create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7106
7107     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7109
7110     r = MsiDatabaseExport(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7112
7113     read_file_data("forcecodepage.idt", buffer);
7114     ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
7115        "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7116
7117     create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
7118
7119     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7120     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_SUCCESS, got %d\n", r);
7121
7122     MsiCloseHandle(hdb);
7123     DeleteFileA(msifile);
7124     DeleteFileA("forcecodepage.idt");
7125 }
7126
7127 static void test_viewmodify_refresh(void)
7128 {
7129     MSIHANDLE hdb, hview, hrec;
7130     const char *query;
7131     char buffer[MAX_PATH];
7132     UINT r;
7133     DWORD size;
7134
7135     DeleteFile(msifile);
7136
7137     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7138     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7139
7140     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7141     r = run_query(hdb, 0, query);
7142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7143
7144     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7145     r = run_query(hdb, 0, query);
7146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7147
7148     query = "SELECT * FROM `Table`";
7149     r = MsiDatabaseOpenView(hdb, query, &hview);
7150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7151     r = MsiViewExecute(hview, 0);
7152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7153
7154     r = MsiViewFetch(hview, &hrec);
7155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7156
7157     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7158     r = run_query(hdb, 0, query);
7159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7160
7161     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7163
7164     size = MAX_PATH;
7165     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7167     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7168     ok(size == 2, "Expected 2, got %d\n", size);
7169
7170     r = MsiRecordGetInteger(hrec, 2);
7171     ok(r == 2, "Expected 2, got %d\n", r);
7172
7173     MsiCloseHandle(hrec);
7174     MsiViewClose(hview);
7175     MsiCloseHandle(hview);
7176
7177     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7178     r = run_query(hdb, 0, query);
7179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7180
7181     query = "SELECT * FROM `Table` WHERE `B` = 3";
7182     r = MsiDatabaseOpenView(hdb, query, &hview);
7183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7184     r = MsiViewExecute(hview, 0);
7185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7186
7187     r = MsiViewFetch(hview, &hrec);
7188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7189
7190     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7191     r = run_query(hdb, 0, query);
7192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7193
7194     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7195     r = run_query(hdb, 0, query);
7196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7197
7198     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7200
7201     size = MAX_PATH;
7202     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7204     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7205     ok(size == 5, "Expected 5, got %d\n", size);
7206
7207     r = MsiRecordGetInteger(hrec, 2);
7208     ok(r == 2, "Expected 2, got %d\n", r);
7209
7210     MsiCloseHandle(hrec);
7211     MsiViewClose(hview);
7212     MsiCloseHandle(hview);
7213     MsiCloseHandle(hdb);
7214     DeleteFileA(msifile);
7215 }
7216
7217 static void test_where_viewmodify(void)
7218 {
7219     MSIHANDLE hdb, hview, hrec;
7220     const char *query;
7221     UINT r;
7222
7223     DeleteFile(msifile);
7224
7225     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7227
7228     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7229     r = run_query(hdb, 0, query);
7230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7231
7232     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7233     r = run_query(hdb, 0, query);
7234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7235
7236     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7237     r = run_query(hdb, 0, query);
7238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7239
7240     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7241     r = run_query(hdb, 0, query);
7242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7243
7244     /* `B` = 3 doesn't match, but the view shouldn't be executed */
7245     query = "SELECT * FROM `Table` WHERE `B` = 3";
7246     r = MsiDatabaseOpenView(hdb, query, &hview);
7247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7248
7249     hrec = MsiCreateRecord(2);
7250     MsiRecordSetInteger(hrec, 1, 7);
7251     MsiRecordSetInteger(hrec, 2, 8);
7252
7253     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7255
7256     MsiCloseHandle(hrec);
7257     MsiViewClose(hview);
7258     MsiCloseHandle(hview);
7259
7260     query = "SELECT * FROM `Table` WHERE `A` = 7";
7261     r = MsiDatabaseOpenView(hdb, query, &hview);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263     r = MsiViewExecute(hview, 0);
7264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7265
7266     r = MsiViewFetch(hview, &hrec);
7267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7268
7269     r = MsiRecordGetInteger(hrec, 1);
7270     ok(r == 7, "Expected 7, got %d\n", r);
7271
7272     r = MsiRecordGetInteger(hrec, 2);
7273     ok(r == 8, "Expected 8, got %d\n", r);
7274
7275     MsiRecordSetInteger(hrec, 2, 9);
7276
7277     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7279
7280     MsiCloseHandle(hrec);
7281     MsiViewClose(hview);
7282     MsiCloseHandle(hview);
7283
7284     query = "SELECT * FROM `Table` WHERE `A` = 7";
7285     r = MsiDatabaseOpenView(hdb, query, &hview);
7286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287     r = MsiViewExecute(hview, 0);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289
7290     r = MsiViewFetch(hview, &hrec);
7291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7292
7293     r = MsiRecordGetInteger(hrec, 1);
7294     ok(r == 7, "Expected 7, got %d\n", r);
7295
7296     r = MsiRecordGetInteger(hrec, 2);
7297     ok(r == 9, "Expected 9, got %d\n", r);
7298
7299     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7300     r = run_query(hdb, 0, query);
7301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7302
7303     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7305
7306     r = MsiRecordGetInteger(hrec, 1);
7307     ok(r == 7, "Expected 7, got %d\n", r);
7308
7309     r = MsiRecordGetInteger(hrec, 2);
7310     ok(r == 10, "Expected 10, got %d\n", r);
7311
7312     MsiCloseHandle(hrec);
7313     MsiViewClose(hview);
7314     MsiCloseHandle(hview);
7315     MsiCloseHandle(hdb);
7316 }
7317
7318 static BOOL create_storage(LPCSTR name)
7319 {
7320     WCHAR nameW[MAX_PATH];
7321     IStorage *stg;
7322     IStream *stm;
7323     HRESULT hr;
7324     DWORD count;
7325     BOOL res = FALSE;
7326
7327     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7328     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7329                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7330     if (FAILED(hr))
7331         return FALSE;
7332
7333     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7334                                0, 0, &stm);
7335     if (FAILED(hr))
7336         goto done;
7337
7338     hr = IStream_Write(stm, "stgdata", 8, &count);
7339     if (SUCCEEDED(hr))
7340         res = TRUE;
7341
7342 done:
7343     IStream_Release(stm);
7344     IStorage_Release(stg);
7345
7346     return res;
7347 }
7348
7349 static void test_storages_table(void)
7350 {
7351     MSIHANDLE hdb, hview, hrec;
7352     IStorage *stg, *inner;
7353     IStream *stm;
7354     char file[MAX_PATH];
7355     char buf[MAX_PATH];
7356     WCHAR name[MAX_PATH];
7357     LPCSTR query;
7358     HRESULT hr;
7359     DWORD size;
7360     UINT r;
7361
7362     hdb = create_db();
7363     ok(hdb, "failed to create db\n");
7364
7365     r = MsiDatabaseCommit(hdb);
7366     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7367
7368     MsiCloseHandle(hdb);
7369
7370     r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb);
7371     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7372
7373     /* check the column types */
7374     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7375     ok(hrec, "failed to get column info hrecord\n");
7376     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7377     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7378
7379     MsiCloseHandle(hrec);
7380
7381     /* now try the names */
7382     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7383     ok(hrec, "failed to get column info hrecord\n");
7384     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7385     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7386
7387     MsiCloseHandle(hrec);
7388
7389     create_storage("storage.bin");
7390
7391     hrec = MsiCreateRecord(2);
7392     MsiRecordSetString(hrec, 1, "stgname");
7393
7394     r = MsiRecordSetStream(hrec, 2, "storage.bin");
7395     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7396
7397     DeleteFileA("storage.bin");
7398
7399     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7400     r = MsiDatabaseOpenView(hdb, query, &hview);
7401     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7402
7403     r = MsiViewExecute(hview, hrec);
7404     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7405
7406     MsiCloseHandle(hrec);
7407     MsiViewClose(hview);
7408     MsiCloseHandle(hview);
7409
7410     query = "SELECT `Name`, `Data` FROM `_Storages`";
7411     r = MsiDatabaseOpenView(hdb, query, &hview);
7412     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7413
7414     r = MsiViewExecute(hview, 0);
7415     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7416
7417     r = MsiViewFetch(hview, &hrec);
7418     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7419
7420     size = MAX_PATH;
7421     r = MsiRecordGetString(hrec, 1, file, &size);
7422     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7423     ok(!lstrcmp(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7424
7425     size = MAX_PATH;
7426     lstrcpyA(buf, "apple");
7427     r = MsiRecordReadStream(hrec, 2, buf, &size);
7428     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7429     ok(!lstrcmp(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7430     ok(size == 0, "Expected 0, got %d\n", size);
7431
7432     MsiCloseHandle(hrec);
7433
7434     r = MsiViewFetch(hview, &hrec);
7435     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7436
7437     MsiViewClose(hview);
7438     MsiCloseHandle(hview);
7439
7440     MsiDatabaseCommit(hdb);
7441     MsiCloseHandle(hdb);
7442
7443     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7444     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7445                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7446     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7447     ok(stg != NULL, "Expected non-NULL storage\n");
7448
7449     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7450     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7451                               NULL, 0, &inner);
7452     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7453     ok(inner != NULL, "Expected non-NULL storage\n");
7454
7455     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7456     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7457     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7458     ok(stm != NULL, "Expected non-NULL stream\n");
7459
7460     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7461     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7462     ok(size == 8, "Expected 8, got %d\n", size);
7463     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7464
7465     IStream_Release(stm);
7466     IStorage_Release(inner);
7467
7468     IStorage_Release(stg);
7469     DeleteFileA(msifile);
7470 }
7471
7472 static void test_dbtopackage(void)
7473 {
7474     MSIHANDLE hdb, hpkg;
7475     CHAR package[12], buf[MAX_PATH];
7476     DWORD size;
7477     UINT r;
7478
7479     /* create an empty database, transact mode */
7480     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7481     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7482
7483     set_summary_info(hdb);
7484
7485     r = create_directory_table(hdb);
7486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7487
7488     r = create_custom_action_table(hdb);
7489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7490
7491     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7492     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7493
7494     sprintf(package, "#%u", hdb);
7495     r = MsiOpenPackage(package, &hpkg);
7496     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7497     {
7498         skip("Not enough rights to perform tests\n");
7499         goto error;
7500     }
7501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7502
7503     /* property is not set yet */
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     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7509     ok(size == 0, "Expected 0, got %d\n", size);
7510
7511     /* run the custom action to set the property */
7512     r = MsiDoAction(hpkg, "SetProp");
7513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7514
7515     /* property is now set */
7516     size = MAX_PATH;
7517     lstrcpyA(buf, "kiwi");
7518     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7520     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7521     ok(size == 5, "Expected 5, got %d\n", size);
7522
7523     MsiCloseHandle(hpkg);
7524
7525     /* reset the package */
7526     r = MsiOpenPackage(package, &hpkg);
7527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7528
7529     /* property is not set anymore */
7530     size = MAX_PATH;
7531     lstrcpyA(buf, "kiwi");
7532     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7534     todo_wine
7535     {
7536         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7537         ok(size == 0, "Expected 0, got %d\n", size);
7538     }
7539
7540     MsiCloseHandle(hdb);
7541     MsiCloseHandle(hpkg);
7542
7543     /* create an empty database, direct mode */
7544     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATEDIRECT, &hdb);
7545     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7546
7547     set_summary_info(hdb);
7548
7549     r = create_directory_table(hdb);
7550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7551
7552     r = create_custom_action_table(hdb);
7553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7554
7555     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7557
7558     sprintf(package, "#%u", hdb);
7559     r = MsiOpenPackage(package, &hpkg);
7560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7561
7562     /* property is not set yet */
7563     size = MAX_PATH;
7564     lstrcpyA(buf, "kiwi");
7565     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7566     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7567     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7568     ok(size == 0, "Expected 0, got %d\n", size);
7569
7570     /* run the custom action to set the property */
7571     r = MsiDoAction(hpkg, "SetProp");
7572     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7573
7574     /* property is now set */
7575     size = MAX_PATH;
7576     lstrcpyA(buf, "kiwi");
7577     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7579     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7580     ok(size == 5, "Expected 5, got %d\n", size);
7581
7582     MsiCloseHandle(hpkg);
7583
7584     /* reset the package */
7585     r = MsiOpenPackage(package, &hpkg);
7586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7587
7588     /* property is not set anymore */
7589     size = MAX_PATH;
7590     lstrcpyA(buf, "kiwi");
7591     r = MsiGetProperty(hpkg, "MYPROP", buf, &size);
7592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7593     todo_wine
7594     {
7595         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7596         ok(size == 0, "Expected 0, got %d\n", size);
7597     }
7598
7599     MsiCloseHandle(hpkg);
7600
7601 error:
7602     MsiCloseHandle(hdb);
7603     DeleteFileA(msifile);
7604 }
7605
7606 static void test_droptable(void)
7607 {
7608     MSIHANDLE hdb, hview, hrec;
7609     CHAR buf[MAX_PATH];
7610     LPCSTR query;
7611     DWORD size;
7612     UINT r;
7613
7614     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7616
7617     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7618     r = run_query(hdb, 0, query);
7619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7620
7621     query = "SELECT * FROM `One`";
7622     r = do_query(hdb, query, &hrec);
7623     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7624
7625     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7626     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7628     r = MsiViewExecute(hview, 0);
7629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7630
7631     r = MsiViewFetch(hview, &hrec);
7632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7633
7634     size = MAX_PATH;
7635     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7637     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7638
7639     MsiCloseHandle(hrec);
7640     MsiViewClose(hview);
7641     MsiCloseHandle(hview);
7642
7643     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7644     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7646     r = MsiViewExecute(hview, 0);
7647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7648
7649     r = MsiViewFetch(hview, &hrec);
7650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7651
7652     size = MAX_PATH;
7653     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7655     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7656
7657     r = MsiRecordGetInteger(hrec, 2);
7658     ok(r == 1, "Expected 1, got %d\n", r);
7659
7660     size = MAX_PATH;
7661     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7663     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7664
7665     MsiCloseHandle(hrec);
7666
7667     r = MsiViewFetch(hview, &hrec);
7668     ok(r == ERROR_NO_MORE_ITEMS,
7669        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7670
7671     MsiViewClose(hview);
7672     MsiCloseHandle(hview);
7673
7674     query = "DROP `One`";
7675     r = run_query(hdb, 0, query);
7676     ok(r == ERROR_BAD_QUERY_SYNTAX,
7677        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7678
7679     query = "DROP TABLE";
7680     r = run_query(hdb, 0, query);
7681     ok(r == ERROR_BAD_QUERY_SYNTAX,
7682        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7683
7684     query = "DROP TABLE `One`";
7685     hview = 0;
7686     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7688     r = MsiViewExecute(hview, 0);
7689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7690
7691     r = MsiViewFetch(hview, &hrec);
7692     ok(r == ERROR_FUNCTION_FAILED,
7693        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7694
7695     MsiViewClose(hview);
7696     MsiCloseHandle(hview);
7697
7698     query = "SELECT * FROM `IDontExist`";
7699     r = do_query(hdb, query, &hrec);
7700     ok(r == ERROR_BAD_QUERY_SYNTAX,
7701        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7702
7703     query = "SELECT * FROM `One`";
7704     r = do_query(hdb, query, &hrec);
7705     ok(r == ERROR_BAD_QUERY_SYNTAX,
7706        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7707
7708     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7709     r = run_query(hdb, 0, query);
7710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7711
7712     query = "DROP TABLE One";
7713     r = run_query(hdb, 0, query);
7714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7715
7716     query = "SELECT * FROM `One`";
7717     r = do_query(hdb, query, &hrec);
7718     ok(r == ERROR_BAD_QUERY_SYNTAX,
7719        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7720
7721     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7722     r = do_query(hdb, query, &hrec);
7723     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7724
7725     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7726     r = do_query(hdb, query, &hrec);
7727     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7728
7729     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7730     r = run_query(hdb, 0, query);
7731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7732
7733     query = "SELECT * FROM `One`";
7734     r = do_query(hdb, query, &hrec);
7735     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7736
7737     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7738     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7740     r = MsiViewExecute(hview, 0);
7741     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7742
7743     r = MsiViewFetch(hview, &hrec);
7744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7745
7746     size = MAX_PATH;
7747     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7749     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7750
7751     MsiCloseHandle(hrec);
7752     MsiViewClose(hview);
7753     MsiCloseHandle(hview);
7754
7755     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7756     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7758     r = MsiViewExecute(hview, 0);
7759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7760
7761     r = MsiViewFetch(hview, &hrec);
7762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7763
7764     size = MAX_PATH;
7765     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7767     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7768
7769     r = MsiRecordGetInteger(hrec, 2);
7770     ok(r == 1, "Expected 1, got %d\n", r);
7771
7772     size = MAX_PATH;
7773     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7775     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7776
7777     MsiCloseHandle(hrec);
7778
7779     r = MsiViewFetch(hview, &hrec);
7780     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7781
7782     size = MAX_PATH;
7783     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7784     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7785     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7786
7787     r = MsiRecordGetInteger(hrec, 2);
7788     ok(r == 2, "Expected 2, got %d\n", r);
7789
7790     size = MAX_PATH;
7791     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7793     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7794
7795     MsiCloseHandle(hrec);
7796
7797     r = MsiViewFetch(hview, &hrec);
7798     ok(r == ERROR_NO_MORE_ITEMS,
7799        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7800
7801     MsiViewClose(hview);
7802     MsiCloseHandle(hview);
7803
7804     query = "DROP TABLE One";
7805     r = run_query(hdb, 0, query);
7806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7807
7808     query = "SELECT * FROM `One`";
7809     r = do_query(hdb, query, &hrec);
7810     ok(r == ERROR_BAD_QUERY_SYNTAX,
7811        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7812
7813     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7814     r = do_query(hdb, query, &hrec);
7815     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7816
7817     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7818     r = do_query(hdb, query, &hrec);
7819     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7820
7821     MsiCloseHandle(hdb);
7822     DeleteFileA(msifile);
7823 }
7824
7825 static void test_dbmerge(void)
7826 {
7827     MSIHANDLE hdb, href, hview, hrec;
7828     CHAR buf[MAX_PATH];
7829     LPCSTR query;
7830     DWORD size;
7831     UINT r;
7832
7833     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
7834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7835
7836     r = MsiOpenDatabase("refdb.msi", MSIDBOPEN_CREATE, &href);
7837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7838
7839     /* hDatabase is invalid */
7840     r = MsiDatabaseMergeA(0, href, "MergeErrors");
7841     ok(r == ERROR_INVALID_HANDLE,
7842        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7843
7844     /* hDatabaseMerge is invalid */
7845     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7846     ok(r == ERROR_INVALID_HANDLE,
7847        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7848
7849     /* szTableName is NULL */
7850     r = MsiDatabaseMergeA(hdb, href, NULL);
7851     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7852
7853     /* szTableName is empty */
7854     r = MsiDatabaseMergeA(hdb, href, "");
7855     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7856
7857     /* both DBs empty, szTableName is valid */
7858     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7860
7861     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7862     r = run_query(hdb, 0, query);
7863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7864
7865     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7866     r = run_query(href, 0, query);
7867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7868
7869     /* column types don't match */
7870     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7871     ok(r == ERROR_DATATYPE_MISMATCH,
7872        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7873
7874     /* nothing in MergeErrors */
7875     query = "SELECT * FROM `MergeErrors`";
7876     r = do_query(hdb, query, &hrec);
7877     ok(r == ERROR_BAD_QUERY_SYNTAX,
7878        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7879
7880     query = "DROP TABLE `One`";
7881     r = run_query(hdb, 0, query);
7882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7883
7884     query = "DROP TABLE `One`";
7885     r = run_query(href, 0, query);
7886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7887
7888     query = "CREATE TABLE `One` ( "
7889         "`A` CHAR(72), "
7890         "`B` CHAR(56), "
7891         "`C` CHAR(64) LOCALIZABLE, "
7892         "`D` LONGCHAR, "
7893         "`E` CHAR(72) NOT NULL, "
7894         "`F` CHAR(56) NOT NULL, "
7895         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7896         "`H` LONGCHAR NOT NULL "
7897         "PRIMARY KEY `A` )";
7898     r = run_query(hdb, 0, query);
7899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7900
7901     query = "CREATE TABLE `One` ( "
7902         "`A` CHAR(64), "
7903         "`B` CHAR(64), "
7904         "`C` CHAR(64), "
7905         "`D` CHAR(64), "
7906         "`E` CHAR(64) NOT NULL, "
7907         "`F` CHAR(64) NOT NULL, "
7908         "`G` CHAR(64) NOT NULL, "
7909         "`H` CHAR(64) NOT NULL "
7910         "PRIMARY KEY `A` )";
7911     r = run_query(href, 0, query);
7912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7913
7914     /* column sting types don't match exactly */
7915     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7916     ok(r == ERROR_SUCCESS,
7917        "Expected ERROR_SUCCESS, got %d\n", r);
7918
7919     /* nothing in MergeErrors */
7920     query = "SELECT * FROM `MergeErrors`";
7921     r = do_query(hdb, query, &hrec);
7922     ok(r == ERROR_BAD_QUERY_SYNTAX,
7923        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7924
7925     query = "DROP TABLE `One`";
7926     r = run_query(hdb, 0, query);
7927     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7928
7929     query = "DROP TABLE `One`";
7930     r = run_query(href, 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(hdb, 0, query);
7935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7936
7937     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
7938     r = run_query(href, 0, query);
7939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7940
7941     /* column names don't match */
7942     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7943     ok(r == ERROR_DATATYPE_MISMATCH,
7944        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7945
7946     /* nothing in MergeErrors */
7947     query = "SELECT * FROM `MergeErrors`";
7948     r = do_query(hdb, query, &hrec);
7949     ok(r == ERROR_BAD_QUERY_SYNTAX,
7950        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7951
7952     query = "DROP TABLE `One`";
7953     r = run_query(hdb, 0, query);
7954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7955
7956     query = "DROP TABLE `One`";
7957     r = run_query(href, 0, query);
7958     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7959
7960     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7961     r = run_query(hdb, 0, query);
7962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7963
7964     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
7965     r = run_query(href, 0, query);
7966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7967
7968     /* primary keys don't match */
7969     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7970     ok(r == ERROR_DATATYPE_MISMATCH,
7971        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7972
7973     /* nothing in MergeErrors */
7974     query = "SELECT * FROM `MergeErrors`";
7975     r = do_query(hdb, query, &hrec);
7976     ok(r == ERROR_BAD_QUERY_SYNTAX,
7977        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7978
7979     query = "DROP TABLE `One`";
7980     r = run_query(hdb, 0, query);
7981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7982
7983     query = "DROP TABLE `One`";
7984     r = run_query(href, 0, query);
7985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7986
7987     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7988     r = run_query(hdb, 0, query);
7989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7990
7991     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
7992     r = run_query(href, 0, query);
7993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7994
7995     /* number of primary keys doesn't match */
7996     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7997     ok(r == ERROR_DATATYPE_MISMATCH,
7998        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7999
8000     /* nothing in MergeErrors */
8001     query = "SELECT * FROM `MergeErrors`";
8002     r = do_query(hdb, query, &hrec);
8003     ok(r == ERROR_BAD_QUERY_SYNTAX,
8004        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8005
8006     query = "DROP TABLE `One`";
8007     r = run_query(hdb, 0, query);
8008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8009
8010     query = "DROP TABLE `One`";
8011     r = run_query(href, 0, query);
8012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8013
8014     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8015     r = run_query(hdb, 0, query);
8016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8017
8018     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8019     r = run_query(href, 0, query);
8020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8021
8022     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8023     r = run_query(href, 0, query);
8024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8025
8026     /* number of columns doesn't match */
8027     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8029
8030     query = "SELECT * FROM `One`";
8031     r = do_query(hdb, query, &hrec);
8032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8033
8034     r = MsiRecordGetInteger(hrec, 1);
8035     ok(r == 1, "Expected 1, got %d\n", r);
8036
8037     r = MsiRecordGetInteger(hrec, 2);
8038     ok(r == 2, "Expected 2, got %d\n", r);
8039
8040     r = MsiRecordGetInteger(hrec, 3);
8041     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8042
8043     MsiCloseHandle(hrec);
8044
8045     /* nothing in MergeErrors */
8046     query = "SELECT * FROM `MergeErrors`";
8047     r = do_query(hdb, query, &hrec);
8048     ok(r == ERROR_BAD_QUERY_SYNTAX,
8049        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8050
8051     query = "DROP TABLE `One`";
8052     r = run_query(hdb, 0, query);
8053     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8054
8055     query = "DROP TABLE `One`";
8056     r = run_query(href, 0, query);
8057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8058
8059     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8060     r = run_query(hdb, 0, query);
8061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8062
8063     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8064     r = run_query(href, 0, query);
8065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8066
8067     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8068     r = run_query(href, 0, query);
8069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8070
8071     /* number of columns doesn't match */
8072     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8074
8075     query = "SELECT * FROM `One`";
8076     r = do_query(hdb, query, &hrec);
8077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8078
8079     r = MsiRecordGetInteger(hrec, 1);
8080     ok(r == 1, "Expected 1, got %d\n", r);
8081
8082     r = MsiRecordGetInteger(hrec, 2);
8083     ok(r == 2, "Expected 2, got %d\n", r);
8084
8085     r = MsiRecordGetInteger(hrec, 3);
8086     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8087
8088     MsiCloseHandle(hrec);
8089
8090     /* nothing in MergeErrors */
8091     query = "SELECT * FROM `MergeErrors`";
8092     r = do_query(hdb, query, &hrec);
8093     ok(r == ERROR_BAD_QUERY_SYNTAX,
8094        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8095
8096     query = "DROP TABLE `One`";
8097     r = run_query(hdb, 0, query);
8098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8099
8100     query = "DROP TABLE `One`";
8101     r = run_query(href, 0, query);
8102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8103
8104     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8105     r = run_query(hdb, 0, query);
8106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8107
8108     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
8109     r = run_query(hdb, 0, query);
8110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8111
8112     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8113     r = run_query(hdb, 0, query);
8114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8115
8116     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8117     r = run_query(href, 0, query);
8118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8119
8120     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8121     r = run_query(href, 0, query);
8122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8123
8124     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
8125     r = run_query(href, 0, query);
8126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8127
8128     /* primary keys match, rows do not */
8129     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8130     ok(r == ERROR_FUNCTION_FAILED,
8131        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8132
8133     /* nothing in MergeErrors */
8134     query = "SELECT * FROM `MergeErrors`";
8135     r = do_query(hdb, query, &hrec);
8136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8137
8138     size = MAX_PATH;
8139     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8141     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8142
8143     r = MsiRecordGetInteger(hrec, 2);
8144     ok(r == 2, "Expected 2, got %d\n", r);
8145
8146     MsiCloseHandle(hrec);
8147
8148     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8150
8151     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8153
8154     size = MAX_PATH;
8155     r = MsiRecordGetString(hrec, 1, buf, &size);
8156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8157     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8158
8159     size = MAX_PATH;
8160     r = MsiRecordGetString(hrec, 2, buf, &size);
8161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8162     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8163        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8164
8165     MsiCloseHandle(hrec);
8166
8167     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8169
8170     size = MAX_PATH;
8171     r = MsiRecordGetString(hrec, 1, buf, &size);
8172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8173     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8174
8175     size = MAX_PATH;
8176     r = MsiRecordGetString(hrec, 2, buf, &size);
8177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8178     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8179
8180     MsiCloseHandle(hrec);
8181     MsiViewClose(hview);
8182     MsiCloseHandle(hview);
8183
8184     query = "DROP TABLE `MergeErrors`";
8185     r = run_query(hdb, 0, query);
8186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8187
8188     query = "DROP TABLE `One`";
8189     r = run_query(hdb, 0, query);
8190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8191
8192     query = "DROP TABLE `One`";
8193     r = run_query(href, 0, query);
8194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8195
8196     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8197     r = run_query(href, 0, query);
8198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8199
8200     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8201     r = run_query(href, 0, query);
8202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8203
8204     /* table from merged database is not in target database */
8205     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8207
8208     query = "SELECT * FROM `One`";
8209     r = do_query(hdb, query, &hrec);
8210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8211
8212     r = MsiRecordGetInteger(hrec, 1);
8213     ok(r == 1, "Expected 1, got %d\n", r);
8214
8215     size = MAX_PATH;
8216     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8218     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8219
8220     MsiCloseHandle(hrec);
8221
8222     /* nothing in MergeErrors */
8223     query = "SELECT * FROM `MergeErrors`";
8224     r = do_query(hdb, query, &hrec);
8225     ok(r == ERROR_BAD_QUERY_SYNTAX,
8226        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8227
8228     query = "DROP TABLE `One`";
8229     r = run_query(hdb, 0, query);
8230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8231
8232     query = "DROP TABLE `One`";
8233     r = run_query(href, 0, query);
8234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8235
8236     query = "CREATE TABLE `One` ( "
8237             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8238     r = run_query(hdb, 0, query);
8239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8240
8241     query = "CREATE TABLE `One` ( "
8242             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8243     r = run_query(href, 0, query);
8244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8245
8246     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8247     r = run_query(href, 0, query);
8248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8249
8250     /* primary key is string */
8251     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8253
8254     query = "SELECT * FROM `One`";
8255     r = do_query(hdb, query, &hrec);
8256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8257
8258     size = MAX_PATH;
8259     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8261     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8262
8263     r = MsiRecordGetInteger(hrec, 2);
8264     ok(r == 1, "Expected 1, got %d\n", r);
8265
8266     MsiCloseHandle(hrec);
8267
8268     /* nothing in MergeErrors */
8269     query = "SELECT * FROM `MergeErrors`";
8270     r = do_query(hdb, query, &hrec);
8271     ok(r == ERROR_BAD_QUERY_SYNTAX,
8272        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8273
8274     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8275
8276     GetCurrentDirectoryA(MAX_PATH, buf);
8277     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8279
8280     query = "DROP TABLE `One`";
8281     r = run_query(hdb, 0, query);
8282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8283
8284     query = "DROP TABLE `One`";
8285     r = run_query(href, 0, query);
8286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8287
8288     query = "CREATE TABLE `One` ( "
8289             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8290     r = run_query(hdb, 0, query);
8291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8292
8293     query = "CREATE TABLE `One` ( "
8294             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8295     r = run_query(href, 0, query);
8296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8297
8298     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8299     r = run_query(href, 0, query);
8300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8301
8302     /* code page does not match */
8303     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8305
8306     query = "SELECT * FROM `One`";
8307     r = do_query(hdb, query, &hrec);
8308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8309
8310     r = MsiRecordGetInteger(hrec, 1);
8311     ok(r == 1, "Expected 1, got %d\n", r);
8312
8313     size = MAX_PATH;
8314     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8316     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8317
8318     MsiCloseHandle(hrec);
8319
8320     /* nothing in MergeErrors */
8321     query = "SELECT * FROM `MergeErrors`";
8322     r = do_query(hdb, query, &hrec);
8323     ok(r == ERROR_BAD_QUERY_SYNTAX,
8324        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8325
8326     query = "DROP TABLE `One`";
8327     r = run_query(hdb, 0, query);
8328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8329
8330     query = "DROP TABLE `One`";
8331     r = run_query(href, 0, query);
8332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8333
8334     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8335     r = run_query(hdb, 0, query);
8336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8337
8338     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8339     r = run_query(href, 0, query);
8340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8341
8342     create_file("binary.dat");
8343     hrec = MsiCreateRecord(1);
8344     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8345
8346     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8347     r = run_query(href, hrec, query);
8348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8349
8350     MsiCloseHandle(hrec);
8351
8352     /* binary data to merge */
8353     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8355
8356     query = "SELECT * FROM `One`";
8357     r = do_query(hdb, query, &hrec);
8358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8359
8360     r = MsiRecordGetInteger(hrec, 1);
8361     ok(r == 1, "Expected 1, got %d\n", r);
8362
8363     size = MAX_PATH;
8364     ZeroMemory(buf, MAX_PATH);
8365     r = MsiRecordReadStream(hrec, 2, buf, &size);
8366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8367     ok(!lstrcmpA(buf, "binary.dat\n"),
8368        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8369
8370     MsiCloseHandle(hrec);
8371
8372     /* nothing in MergeErrors */
8373     query = "SELECT * FROM `MergeErrors`";
8374     r = do_query(hdb, query, &hrec);
8375     ok(r == ERROR_BAD_QUERY_SYNTAX,
8376        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8377
8378     query = "DROP TABLE `One`";
8379     r = run_query(hdb, 0, query);
8380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8381
8382     query = "DROP TABLE `One`";
8383     r = run_query(href, 0, query);
8384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8385
8386     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8387     r = run_query(hdb, 0, query);
8388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8389     r = run_query(href, 0, query);
8390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8391
8392     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8393     r = run_query(href, 0, query);
8394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8395
8396     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8397     r = run_query(href, 0, query);
8398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8399
8400     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8402
8403     query = "SELECT * FROM `One`";
8404     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8406     r = MsiViewExecute(hview, 0);
8407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8408
8409     r = MsiViewFetch(hview, &hrec);
8410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8411
8412     r = MsiRecordGetInteger(hrec, 1);
8413     ok(r == 1, "Expected 1, got %d\n", r);
8414
8415     size = MAX_PATH;
8416     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8418     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8419
8420     MsiCloseHandle(hrec);
8421
8422     r = MsiViewFetch(hview, &hrec);
8423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8424
8425     r = MsiRecordGetInteger(hrec, 1);
8426     ok(r == 2, "Expected 2, got %d\n", r);
8427
8428     size = MAX_PATH;
8429     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8431     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8432
8433     MsiCloseHandle(hrec);
8434
8435     r = MsiViewFetch(hview, &hrec);
8436     ok(r == ERROR_NO_MORE_ITEMS,
8437        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8438
8439     MsiViewClose(hview);
8440     MsiCloseHandle(hview);
8441
8442     MsiCloseHandle(hdb);
8443     MsiCloseHandle(href);
8444     DeleteFileA(msifile);
8445     DeleteFileA("refdb.msi");
8446     DeleteFileA("codepage.idt");
8447     DeleteFileA("binary.dat");
8448 }
8449
8450 static void test_select_with_tablenames(void)
8451 {
8452     MSIHANDLE hdb, view, rec;
8453     LPCSTR query;
8454     UINT r;
8455     int i;
8456
8457     int vals[4][2] = {
8458         {1,12},
8459         {4,12},
8460         {1,15},
8461         {4,15}};
8462
8463     hdb = create_db();
8464     ok(hdb, "failed to create db\n");
8465
8466     /* Build a pair of tables with the same column names, but unique data */
8467     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8468     r = run_query(hdb, 0, query);
8469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8470
8471     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8472     r = run_query(hdb, 0, query);
8473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8474
8475     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8476     r = run_query(hdb, 0, query);
8477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8478
8479     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8480     r = run_query(hdb, 0, query);
8481     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8482
8483     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8484     r = run_query(hdb, 0, query);
8485     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8486
8487     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8488     r = run_query(hdb, 0, query);
8489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8490
8491
8492     /* Test that selection based on prefixing the column with the table
8493      * actually selects the right data */
8494
8495     query = "SELECT T1.A, T2.B FROM T1,T2";
8496     r = MsiDatabaseOpenView(hdb, query, &view);
8497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8498     r = MsiViewExecute(view, 0);
8499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8500
8501     for (i = 0; i < 4; i++)
8502     {
8503         r = MsiViewFetch(view, &rec);
8504         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8505
8506         r = MsiRecordGetInteger(rec, 1);
8507         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8508
8509         r = MsiRecordGetInteger(rec, 2);
8510         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8511
8512         MsiCloseHandle(rec);
8513     }
8514
8515     r = MsiViewFetch(view, &rec);
8516     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8517
8518     MsiViewClose(view);
8519     MsiCloseHandle(view);
8520     MsiCloseHandle(hdb);
8521     DeleteFileA(msifile);
8522 }
8523
8524 static const UINT ordervals[6][3] =
8525 {
8526     { MSI_NULL_INTEGER, 12, 13 },
8527     { 1, 2, 3 },
8528     { 6, 4, 5 },
8529     { 8, 9, 7 },
8530     { 10, 11, MSI_NULL_INTEGER },
8531     { 14, MSI_NULL_INTEGER, 15 }
8532 };
8533
8534 static void test_insertorder(void)
8535 {
8536     MSIHANDLE hdb, view, rec;
8537     LPCSTR query;
8538     UINT r;
8539     int i;
8540
8541     hdb = create_db();
8542     ok(hdb, "failed to create db\n");
8543
8544     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8545     r = run_query(hdb, 0, query);
8546     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8547
8548     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8549     r = run_query(hdb, 0, query);
8550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8551
8552     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8553     r = run_query(hdb, 0, query);
8554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8555
8556     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8557     r = run_query(hdb, 0, query);
8558     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8559
8560     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8561     r = run_query(hdb, 0, query);
8562     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8563
8564     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8565     r = run_query(hdb, 0, query);
8566     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8567
8568     /* fails because the primary key already
8569      * has an MSI_NULL_INTEGER value set above
8570      */
8571     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8572     r = run_query(hdb, 0, query);
8573     ok(r == ERROR_FUNCTION_FAILED,
8574        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8575
8576     /* replicate the error where primary key is set twice */
8577     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8578     r = run_query(hdb, 0, query);
8579     ok(r == ERROR_FUNCTION_FAILED,
8580        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8581
8582     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8583     r = run_query(hdb, 0, query);
8584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8585
8586     query = "INSERT INTO `T` VALUES ( 16 )";
8587     r = run_query(hdb, 0, query);
8588     ok(r == ERROR_BAD_QUERY_SYNTAX,
8589        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8590
8591     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8592     r = run_query(hdb, 0, query);
8593     ok(r == ERROR_BAD_QUERY_SYNTAX,
8594        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8595
8596     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8597     r = run_query(hdb, 0, query);
8598     ok(r == ERROR_BAD_QUERY_SYNTAX,
8599        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8600
8601     query = "SELECT * FROM `T`";
8602     r = MsiDatabaseOpenView(hdb, query, &view);
8603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8604     r = MsiViewExecute(view, 0);
8605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8606
8607     for (i = 0; i < 6; i++)
8608     {
8609         r = MsiViewFetch(view, &rec);
8610         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8611
8612         r = MsiRecordGetInteger(rec, 1);
8613         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8614
8615         r = MsiRecordGetInteger(rec, 2);
8616         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8617
8618         r = MsiRecordGetInteger(rec, 3);
8619         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8620
8621         MsiCloseHandle(rec);
8622     }
8623
8624     r = MsiViewFetch(view, &rec);
8625     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8626
8627     MsiViewClose(view);
8628     MsiCloseHandle(view);
8629
8630     query = "DELETE FROM `T` WHERE `A` IS NULL";
8631     r = run_query(hdb, 0, query);
8632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8633
8634     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8635     r = run_query(hdb, 0, query);
8636     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8637
8638     query = "SELECT * FROM `T`";
8639     r = MsiDatabaseOpenView(hdb, query, &view);
8640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8641     r = MsiViewExecute(view, 0);
8642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8643
8644     for (i = 0; i < 6; i++)
8645     {
8646         r = MsiViewFetch(view, &rec);
8647         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8648
8649         r = MsiRecordGetInteger(rec, 1);
8650         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8651
8652         r = MsiRecordGetInteger(rec, 2);
8653         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8654
8655         r = MsiRecordGetInteger(rec, 3);
8656         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8657
8658         MsiCloseHandle(rec);
8659     }
8660
8661     r = MsiViewFetch(view, &rec);
8662     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8663
8664     MsiViewClose(view);
8665     MsiCloseHandle(view);
8666     MsiCloseHandle(hdb);
8667     DeleteFileA(msifile);
8668 }
8669
8670 static void test_columnorder(void)
8671 {
8672     MSIHANDLE hdb, view, rec;
8673     char buf[MAX_PATH];
8674     LPCSTR query;
8675     DWORD sz;
8676     UINT r;
8677
8678     hdb = create_db();
8679     ok(hdb, "failed to create db\n");
8680
8681     /* Each column is a slot:
8682      * ---------------------
8683      * | B | C | A | E | D |
8684      * ---------------------
8685      *
8686      * When a column is selected as a primary key,
8687      * the column occupying the nth primary key slot is swapped
8688      * with the current position of the primary key in question:
8689      *
8690      * set primary key `D`
8691      * ---------------------    ---------------------
8692      * | B | C | A | E | D | -> | D | C | A | E | B |
8693      * ---------------------    ---------------------
8694      *
8695      * set primary key `E`
8696      * ---------------------    ---------------------
8697      * | D | C | A | E | B | -> | D | E | A | C | B |
8698      * ---------------------    ---------------------
8699      */
8700
8701     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8702             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8703             "PRIMARY KEY `D`, `E`)";
8704     r = run_query(hdb, 0, query);
8705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8706
8707     query = "SELECT * FROM `T`";
8708     r = MsiDatabaseOpenView(hdb, query, &view);
8709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8710
8711     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8713
8714     sz = MAX_PATH;
8715     lstrcpyA(buf, "kiwi");
8716     r = MsiRecordGetString(rec, 1, buf, &sz);
8717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8718     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8719
8720     sz = MAX_PATH;
8721     lstrcpyA(buf, "kiwi");
8722     r = MsiRecordGetString(rec, 2, buf, &sz);
8723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8724     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8725
8726     sz = MAX_PATH;
8727     lstrcpyA(buf, "kiwi");
8728     r = MsiRecordGetString(rec, 3, buf, &sz);
8729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8730     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8731
8732     sz = MAX_PATH;
8733     lstrcpyA(buf, "kiwi");
8734     r = MsiRecordGetString(rec, 4, buf, &sz);
8735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8736     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8737
8738     sz = MAX_PATH;
8739     lstrcpyA(buf, "kiwi");
8740     r = MsiRecordGetString(rec, 5, buf, &sz);
8741     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8742     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8743
8744     MsiCloseHandle(rec);
8745
8746     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8748
8749     sz = MAX_PATH;
8750     lstrcpyA(buf, "kiwi");
8751     r = MsiRecordGetString(rec, 1, buf, &sz);
8752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8753     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8754
8755     sz = MAX_PATH;
8756     lstrcpyA(buf, "kiwi");
8757     r = MsiRecordGetString(rec, 2, buf, &sz);
8758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8759     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8760
8761     sz = MAX_PATH;
8762     lstrcpyA(buf, "kiwi");
8763     r = MsiRecordGetString(rec, 3, buf, &sz);
8764     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8765     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8766
8767     sz = MAX_PATH;
8768     lstrcpyA(buf, "kiwi");
8769     r = MsiRecordGetString(rec, 4, buf, &sz);
8770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8771     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8772
8773     sz = MAX_PATH;
8774     lstrcpyA(buf, "kiwi");
8775     r = MsiRecordGetString(rec, 5, buf, &sz);
8776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8777     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8778
8779     MsiCloseHandle(rec);
8780     MsiViewClose(view);
8781     MsiCloseHandle(view);
8782
8783     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8784             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8785     r = run_query(hdb, 0, query);
8786     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8787
8788     query = "SELECT * FROM `T`";
8789     r = do_query(hdb, query, &rec);
8790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8791
8792     sz = MAX_PATH;
8793     lstrcpyA(buf, "kiwi");
8794     r = MsiRecordGetString(rec, 1, buf, &sz);
8795     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8796     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8797
8798     r = MsiRecordGetInteger(rec, 2);
8799     ok(r == 3, "Expected 3, got %d\n", r);
8800
8801     sz = MAX_PATH;
8802     lstrcpyA(buf, "kiwi");
8803     r = MsiRecordGetString(rec, 3, buf, &sz);
8804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8805     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8806
8807     r = MsiRecordGetInteger(rec, 4);
8808     ok(r == 2, "Expected 2, got %d\n", r);
8809
8810     r = MsiRecordGetInteger(rec, 5);
8811     ok(r == 1, "Expected 1, got %d\n", r);
8812
8813     MsiCloseHandle(rec);
8814
8815     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8816     r = MsiDatabaseOpenView(hdb, query, &view);
8817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8818     r = MsiViewExecute(view, 0);
8819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8820
8821     r = MsiViewFetch(view, &rec);
8822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8823
8824     sz = MAX_PATH;
8825     lstrcpyA(buf, "kiwi");
8826     r = MsiRecordGetString(rec, 1, buf, &sz);
8827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8828     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8829
8830     r = MsiRecordGetInteger(rec, 2);
8831     ok(r == 1, "Expected 1, got %d\n", r);
8832
8833     sz = MAX_PATH;
8834     lstrcpyA(buf, "kiwi");
8835     r = MsiRecordGetString(rec, 3, buf, &sz);
8836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8837     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8838
8839     MsiCloseHandle(rec);
8840
8841     r = MsiViewFetch(view, &rec);
8842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8843
8844     sz = MAX_PATH;
8845     lstrcpyA(buf, "kiwi");
8846     r = MsiRecordGetString(rec, 1, buf, &sz);
8847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8848     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8849
8850     r = MsiRecordGetInteger(rec, 2);
8851     ok(r == 2, "Expected 2, got %d\n", r);
8852
8853     sz = MAX_PATH;
8854     lstrcpyA(buf, "kiwi");
8855     r = MsiRecordGetString(rec, 3, buf, &sz);
8856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8857     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8858
8859     MsiCloseHandle(rec);
8860
8861     r = MsiViewFetch(view, &rec);
8862     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8863
8864     sz = MAX_PATH;
8865     lstrcpyA(buf, "kiwi");
8866     r = MsiRecordGetString(rec, 1, buf, &sz);
8867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8868     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8869
8870     r = MsiRecordGetInteger(rec, 2);
8871     ok(r == 3, "Expected 3, got %d\n", r);
8872
8873     sz = MAX_PATH;
8874     lstrcpyA(buf, "kiwi");
8875     r = MsiRecordGetString(rec, 3, buf, &sz);
8876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8877     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8878
8879     MsiCloseHandle(rec);
8880
8881     r = MsiViewFetch(view, &rec);
8882     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8883
8884     sz = MAX_PATH;
8885     lstrcpyA(buf, "kiwi");
8886     r = MsiRecordGetString(rec, 1, buf, &sz);
8887     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8888     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8889
8890     r = MsiRecordGetInteger(rec, 2);
8891     ok(r == 4, "Expected 4, got %d\n", r);
8892
8893     sz = MAX_PATH;
8894     lstrcpyA(buf, "kiwi");
8895     r = MsiRecordGetString(rec, 3, buf, &sz);
8896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8897     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8898
8899     MsiCloseHandle(rec);
8900
8901     r = MsiViewFetch(view, &rec);
8902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8903
8904     sz = MAX_PATH;
8905     lstrcpyA(buf, "kiwi");
8906     r = MsiRecordGetString(rec, 1, buf, &sz);
8907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8908     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8909
8910     r = MsiRecordGetInteger(rec, 2);
8911     ok(r == 5, "Expected 5, got %d\n", r);
8912
8913     sz = MAX_PATH;
8914     lstrcpyA(buf, "kiwi");
8915     r = MsiRecordGetString(rec, 3, 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
8921     r = MsiViewFetch(view, &rec);
8922     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8923
8924     MsiViewClose(view);
8925     MsiCloseHandle(view);
8926
8927     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8928             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8929             "PRIMARY KEY `C`, `A`, `D`)";
8930     r = run_query(hdb, 0, query);
8931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8932
8933     query = "SELECT * FROM `Z`";
8934     r = MsiDatabaseOpenView(hdb, query, &view);
8935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8936
8937     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8939
8940     sz = MAX_PATH;
8941     lstrcpyA(buf, "kiwi");
8942     r = MsiRecordGetString(rec, 1, buf, &sz);
8943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8944     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8945
8946     sz = MAX_PATH;
8947     lstrcpyA(buf, "kiwi");
8948     r = MsiRecordGetString(rec, 2, buf, &sz);
8949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8950     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8951
8952     sz = MAX_PATH;
8953     lstrcpyA(buf, "kiwi");
8954     r = MsiRecordGetString(rec, 3, buf, &sz);
8955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8956     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8957
8958     sz = MAX_PATH;
8959     lstrcpyA(buf, "kiwi");
8960     r = MsiRecordGetString(rec, 4, buf, &sz);
8961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8962     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8963
8964     sz = MAX_PATH;
8965     lstrcpyA(buf, "kiwi");
8966     r = MsiRecordGetString(rec, 5, buf, &sz);
8967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8968     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8969
8970     MsiCloseHandle(rec);
8971
8972     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8974
8975     sz = MAX_PATH;
8976     lstrcpyA(buf, "kiwi");
8977     r = MsiRecordGetString(rec, 1, buf, &sz);
8978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8979     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8980
8981     sz = MAX_PATH;
8982     lstrcpyA(buf, "kiwi");
8983     r = MsiRecordGetString(rec, 2, buf, &sz);
8984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8985     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8986
8987     sz = MAX_PATH;
8988     lstrcpyA(buf, "kiwi");
8989     r = MsiRecordGetString(rec, 3, buf, &sz);
8990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8991     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8992
8993     sz = MAX_PATH;
8994     lstrcpyA(buf, "kiwi");
8995     r = MsiRecordGetString(rec, 4, 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     sz = MAX_PATH;
9000     lstrcpyA(buf, "kiwi");
9001     r = MsiRecordGetString(rec, 5, buf, &sz);
9002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9003     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9004
9005     MsiCloseHandle(rec);
9006     MsiViewClose(view);
9007     MsiCloseHandle(view);
9008
9009     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
9010             "VALUES ( 1, 2, 'a', 3, 'bc' )";
9011     r = run_query(hdb, 0, query);
9012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9013
9014     query = "SELECT * FROM `Z`";
9015     r = do_query(hdb, query, &rec);
9016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9017
9018     r = MsiRecordGetInteger(rec, 1);
9019     ok(r == 2, "Expected 2, got %d\n", r);
9020
9021     sz = MAX_PATH;
9022     lstrcpyA(buf, "kiwi");
9023     r = MsiRecordGetString(rec, 2, buf, &sz);
9024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9025     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
9026
9027     sz = MAX_PATH;
9028     lstrcpyA(buf, "kiwi");
9029     r = MsiRecordGetString(rec, 3, buf, &sz);
9030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9031     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
9032
9033     r = MsiRecordGetInteger(rec, 4);
9034     ok(r == 3, "Expected 3, got %d\n", r);
9035
9036     r = MsiRecordGetInteger(rec, 5);
9037     ok(r == 1, "Expected 1, got %d\n", r);
9038
9039     MsiCloseHandle(rec);
9040
9041     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
9042     r = MsiDatabaseOpenView(hdb, query, &view);
9043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9044     r = MsiViewExecute(view, 0);
9045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9046
9047     r = MsiViewFetch(view, &rec);
9048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9049
9050     sz = MAX_PATH;
9051     lstrcpyA(buf, "kiwi");
9052     r = MsiRecordGetString(rec, 1, buf, &sz);
9053     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9054     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9055
9056     r = MsiRecordGetInteger(rec, 2);
9057     ok(r == 1, "Expected 1, got %d\n", r);
9058
9059     sz = MAX_PATH;
9060     lstrcpyA(buf, "kiwi");
9061     r = MsiRecordGetString(rec, 3, buf, &sz);
9062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9063     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9064
9065     MsiCloseHandle(rec);
9066
9067     r = MsiViewFetch(view, &rec);
9068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9069
9070     sz = MAX_PATH;
9071     lstrcpyA(buf, "kiwi");
9072     r = MsiRecordGetString(rec, 1, buf, &sz);
9073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9074     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9075
9076     r = MsiRecordGetInteger(rec, 2);
9077     ok(r == 2, "Expected 2, got %d\n", r);
9078
9079     sz = MAX_PATH;
9080     lstrcpyA(buf, "kiwi");
9081     r = MsiRecordGetString(rec, 3, buf, &sz);
9082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9083     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9084
9085     MsiCloseHandle(rec);
9086
9087     r = MsiViewFetch(view, &rec);
9088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9089
9090     sz = MAX_PATH;
9091     lstrcpyA(buf, "kiwi");
9092     r = MsiRecordGetString(rec, 1, buf, &sz);
9093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9094     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9095
9096     r = MsiRecordGetInteger(rec, 2);
9097     ok(r == 3, "Expected 3, got %d\n", r);
9098
9099     sz = MAX_PATH;
9100     lstrcpyA(buf, "kiwi");
9101     r = MsiRecordGetString(rec, 3, buf, &sz);
9102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9103     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9104
9105     MsiCloseHandle(rec);
9106
9107     r = MsiViewFetch(view, &rec);
9108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9109
9110     sz = MAX_PATH;
9111     lstrcpyA(buf, "kiwi");
9112     r = MsiRecordGetString(rec, 1, buf, &sz);
9113     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9114     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9115
9116     r = MsiRecordGetInteger(rec, 2);
9117     ok(r == 4, "Expected 4, got %d\n", r);
9118
9119     sz = MAX_PATH;
9120     lstrcpyA(buf, "kiwi");
9121     r = MsiRecordGetString(rec, 3, buf, &sz);
9122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9123     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9124
9125     MsiCloseHandle(rec);
9126
9127     r = MsiViewFetch(view, &rec);
9128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9129
9130     sz = MAX_PATH;
9131     lstrcpyA(buf, "kiwi");
9132     r = MsiRecordGetString(rec, 1, buf, &sz);
9133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9134     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9135
9136     r = MsiRecordGetInteger(rec, 2);
9137     ok(r == 5, "Expected 5, got %d\n", r);
9138
9139     sz = MAX_PATH;
9140     lstrcpyA(buf, "kiwi");
9141     r = MsiRecordGetString(rec, 3, buf, &sz);
9142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9143     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9144
9145     MsiCloseHandle(rec);
9146
9147     r = MsiViewFetch(view, &rec);
9148     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9149
9150     MsiViewClose(view);
9151     MsiCloseHandle(view);
9152
9153     MsiCloseHandle(hdb);
9154     DeleteFileA(msifile);
9155 }
9156
9157 static void test_createtable(void)
9158 {
9159     MSIHANDLE hdb, htab = 0, hrec = 0;
9160     LPCSTR query;
9161     UINT res;
9162     DWORD size;
9163     char buffer[0x20];
9164
9165     hdb = create_db();
9166     ok(hdb, "failed to create db\n");
9167
9168     query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9169     res = MsiDatabaseOpenView( hdb, query, &htab );
9170     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9171     if(res == ERROR_SUCCESS )
9172     {
9173         res = MsiViewExecute( htab, hrec );
9174         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9175
9176         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9177         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9178
9179         size = sizeof(buffer);
9180         res = MsiRecordGetString(hrec, 1, buffer, &size );
9181         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9182         MsiCloseHandle( hrec );
9183
9184         res = MsiViewClose( htab );
9185         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9186
9187         res = MsiCloseHandle( htab );
9188         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9189     }
9190
9191     query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9192     res = MsiDatabaseOpenView( hdb, query, &htab );
9193     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9194     if(res == ERROR_SUCCESS )
9195     {
9196         res = MsiViewExecute( htab, 0 );
9197         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9198
9199         res = MsiViewClose( htab );
9200         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9201
9202         res = MsiCloseHandle( htab );
9203         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9204
9205         query = "SELECT * FROM `a`";
9206         res = MsiDatabaseOpenView( hdb, query, &htab );
9207         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9208
9209         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9210         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9211
9212         buffer[0] = 0;
9213         size = sizeof(buffer);
9214         res = MsiRecordGetString(hrec, 1, buffer, &size );
9215         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9216         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9217         MsiCloseHandle( hrec );
9218
9219         res = MsiViewClose( htab );
9220         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9221
9222         res = MsiCloseHandle( htab );
9223         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9224
9225         res = MsiDatabaseCommit(hdb);
9226         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9227
9228         res = MsiCloseHandle(hdb);
9229         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9230
9231         res = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
9232         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9233
9234         query = "SELECT * FROM `a`";
9235         res = MsiDatabaseOpenView( hdb, query, &htab );
9236         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9237
9238         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9239         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9240
9241         buffer[0] = 0;
9242         size = sizeof(buffer);
9243         res = MsiRecordGetString(hrec, 1, buffer, &size );
9244         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9245         todo_wine ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9246
9247         res = MsiCloseHandle( hrec );
9248         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9249
9250         res = MsiViewClose( htab );
9251         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9252
9253         res = MsiCloseHandle( htab );
9254         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9255     }
9256
9257     res = MsiDatabaseCommit(hdb);
9258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9259
9260     res = MsiCloseHandle(hdb);
9261     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9262
9263     DeleteFileA(msifile);
9264 }
9265
9266
9267 START_TEST(db)
9268 {
9269     test_msidatabase();
9270     test_msiinsert();
9271     test_msidecomposedesc();
9272     test_msibadqueries();
9273     test_viewmodify();
9274     test_viewgetcolumninfo();
9275     test_getcolinfo();
9276     test_msiexport();
9277     test_longstrings();
9278     test_streamtable();
9279     test_binary();
9280     test_where_not_in_selected();
9281     test_where();
9282     test_msiimport();
9283     test_binary_import();
9284     test_markers();
9285     test_handle_limit();
9286     test_try_transform();
9287     test_join();
9288     test_temporary_table();
9289     test_alter();
9290     test_integers();
9291     test_update();
9292     test_special_tables();
9293     test_tables_order();
9294     test_rows_order();
9295     test_select_markers();
9296     test_viewmodify_update();
9297     test_viewmodify_assign();
9298     test_stringtable();
9299     test_viewmodify_delete();
9300     test_defaultdatabase();
9301     test_order();
9302     test_viewmodify_delete_temporary();
9303     test_deleterow();
9304     test_quotes();
9305     test_carriagereturn();
9306     test_noquotes();
9307     test_forcecodepage();
9308     test_viewmodify_refresh();
9309     test_where_viewmodify();
9310     test_storages_table();
9311     test_dbtopackage();
9312     test_droptable();
9313     test_dbmerge();
9314     test_select_with_tablenames();
9315     test_insertorder();
9316     test_columnorder();
9317     test_suminfo_import();
9318     test_createtable();
9319     test_collation();
9320 }