xref: /reactos/modules/rostests/winetests/msi/db.c (revision c2c66aff)
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 <objidl.h>
27 #include <msi.h>
28 #include <msidefs.h>
29 #include <msiquery.h>
30 
31 #include "wine/test.h"
32 
33 static const char *msifile = "winetest-db.msi";
34 static const char *msifile2 = "winetst2-db.msi";
35 static const char *mstfile = "winetst-db.mst";
36 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','-','d','b','.','m','s','i',0};
37 static const WCHAR msifile2W[] = {'w','i','n','e','t','s','t','2','-','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     DeleteFileW(msifileW);
45 
46     res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb );
47     ok( res == ERROR_OPEN_FAILED, "expected failure\n");
48 
49     res = MsiOpenDatabaseW( msifileW, (LPWSTR)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 = MsiOpenDatabaseW(msifileW, 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( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
63 
64     res = MsiCloseHandle( hdb );
65     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
66     res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
67     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
68 
69     ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "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 = MsiOpenDatabaseW( msifileW, msifile2W, &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( GetFileAttributesA( msifile2 ) == INVALID_FILE_ATTRIBUTES, "uncommitted database should not exist\n");
84 
85     res = MsiOpenDatabaseW( msifileW, msifile2W, &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( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "committed database should exist\n");
95 
96     res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb );
97     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
98 
99     res = MsiDatabaseCommit( hdb );
100     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
101 
102     res = MsiCloseHandle( hdb );
103     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
104 
105     res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_DIRECT, &hdb );
106     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
107 
108     res = MsiCloseHandle( hdb );
109     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
110 
111     res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_TRANSACT, &hdb );
112     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
113 
114     res = MsiCloseHandle( hdb );
115     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
116     ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
117 
118     /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
119     res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
120     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
121 
122     ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
123 
124     res = MsiCloseHandle( hdb );
125     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
126 
127     ok( GetFileAttributesA( msifile ) == INVALID_FILE_ATTRIBUTES, "database should exist\n");
128 
129     res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
130     ok( res == ERROR_SUCCESS , "Failed to open database\n" );
131 
132     res = MsiDatabaseCommit( hdb );
133     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
134 
135     ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
136 
137     res = MsiCloseHandle( hdb );
138     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
139 
140     res = DeleteFileA( msifile2 );
141     ok( res == TRUE, "Failed to delete database\n" );
142 
143     res = DeleteFileA( msifile );
144     ok( res == TRUE, "Failed to delete database\n" );
145 }
146 
147 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
148 {
149     MSIHANDLE hview = 0;
150     UINT r, ret;
151 
152     if (phrec)
153         *phrec = 0;
154 
155     /* open a select query */
156     r = MsiDatabaseOpenViewA(hdb, query, &hview);
157     if (r != ERROR_SUCCESS)
158         return r;
159     r = MsiViewExecute(hview, 0);
160     if (r != ERROR_SUCCESS)
161         return r;
162     ret = MsiViewFetch(hview, phrec);
163     r = MsiViewClose(hview);
164     if (r != ERROR_SUCCESS)
165         return r;
166     r = MsiCloseHandle(hview);
167     if (r != ERROR_SUCCESS)
168         return r;
169     return ret;
170 }
171 
172 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
173 {
174     MSIHANDLE hview = 0;
175     UINT r;
176 
177     r = MsiDatabaseOpenViewA(hdb, query, &hview);
178     if( r != ERROR_SUCCESS )
179         return r;
180 
181     r = MsiViewExecute(hview, hrec);
182     if( r == ERROR_SUCCESS )
183         r = MsiViewClose(hview);
184     MsiCloseHandle(hview);
185     return r;
186 }
187 
188 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
189 {
190     MSIHANDLE hview = 0;
191     UINT r;
192 
193     r = MsiDatabaseOpenViewW(hdb, query, &hview);
194     if( r != ERROR_SUCCESS )
195         return r;
196 
197     r = MsiViewExecute(hview, hrec);
198     if( r == ERROR_SUCCESS )
199         r = MsiViewClose(hview);
200     MsiCloseHandle(hview);
201     return r;
202 }
203 
204 static UINT create_component_table( MSIHANDLE hdb )
205 {
206     return run_query( hdb, 0,
207             "CREATE TABLE `Component` ( "
208             "`Component` CHAR(72) NOT NULL, "
209             "`ComponentId` CHAR(38), "
210             "`Directory_` CHAR(72) NOT NULL, "
211             "`Attributes` SHORT NOT NULL, "
212             "`Condition` CHAR(255), "
213             "`KeyPath` CHAR(72) "
214             "PRIMARY KEY `Component`)" );
215 }
216 
217 static UINT create_custom_action_table( MSIHANDLE hdb )
218 {
219     return run_query( hdb, 0,
220             "CREATE TABLE `CustomAction` ( "
221             "`Action` CHAR(72) NOT NULL, "
222             "`Type` SHORT NOT NULL, "
223             "`Source` CHAR(72), "
224             "`Target` CHAR(255) "
225             "PRIMARY KEY `Action`)" );
226 }
227 
228 static UINT create_directory_table( MSIHANDLE hdb )
229 {
230     return run_query( hdb, 0,
231             "CREATE TABLE `Directory` ( "
232             "`Directory` CHAR(255) NOT NULL, "
233             "`Directory_Parent` CHAR(255), "
234             "`DefaultDir` CHAR(255) NOT NULL "
235             "PRIMARY KEY `Directory`)" );
236 }
237 
238 static UINT create_feature_components_table( MSIHANDLE hdb )
239 {
240     return run_query( hdb, 0,
241             "CREATE TABLE `FeatureComponents` ( "
242             "`Feature_` CHAR(38) NOT NULL, "
243             "`Component_` CHAR(72) NOT NULL "
244             "PRIMARY KEY `Feature_`, `Component_` )" );
245 }
246 
247 static UINT create_std_dlls_table( MSIHANDLE hdb )
248 {
249     return run_query( hdb, 0,
250             "CREATE TABLE `StdDlls` ( "
251             "`File` CHAR(255) NOT NULL, "
252             "`Binary_` CHAR(72) NOT NULL "
253             "PRIMARY KEY `File` )" );
254 }
255 
256 static UINT create_binary_table( MSIHANDLE hdb )
257 {
258     return run_query( hdb, 0,
259             "CREATE TABLE `Binary` ( "
260             "`Name` CHAR(72) NOT NULL, "
261             "`Data` CHAR(72) NOT NULL "
262             "PRIMARY KEY `Name` )" );
263 }
264 
265 #define make_add_entry(type, qtext) \
266     static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
267     { \
268         char insert[] = qtext; \
269         char *query; \
270         UINT sz, r; \
271         sz = strlen(values) + sizeof insert; \
272         query = HeapAlloc(GetProcessHeap(),0,sz); \
273         sprintf(query,insert,values); \
274         r = run_query( hdb, 0, query ); \
275         HeapFree(GetProcessHeap(), 0, query); \
276         return r; \
277     }
278 
279 make_add_entry(component,
280                "INSERT INTO `Component`  "
281                "(`Component`, `ComponentId`, `Directory_`, "
282                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
283 
284 make_add_entry(custom_action,
285                "INSERT INTO `CustomAction`  "
286                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
287 
288 make_add_entry(feature_components,
289                "INSERT INTO `FeatureComponents` "
290                "(`Feature_`, `Component_`) VALUES( %s )")
291 
292 make_add_entry(std_dlls,
293                "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
294 
295 make_add_entry(binary,
296                "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
297 
298 static void test_msiinsert(void)
299 {
300     MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0;
301     UINT r;
302     const char *query;
303     char buf[80];
304     DWORD sz;
305 
306     DeleteFileA(msifile);
307 
308     /* just MsiOpenDatabase should not create a file */
309     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
310     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
311 
312     /* create a table */
313     query = "CREATE TABLE `phone` ( "
314             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
315             "PRIMARY KEY `id`)";
316     r = MsiDatabaseOpenViewA(hdb, query, &hview);
317     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
318     r = MsiViewExecute(hview, 0);
319     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
320     r = MsiViewClose(hview);
321     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
322     r = MsiCloseHandle(hview);
323     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
324 
325     query = "SELECT * FROM phone WHERE number = '8675309'";
326     r = MsiDatabaseOpenViewA(hdb, query, &hview2);
327     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
328     r = MsiViewExecute(hview2, 0);
329     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
330     r = MsiViewFetch(hview2, &hrec);
331     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
332 
333     /* insert a value into it */
334     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
335         "VALUES('1', 'Abe', '8675309')";
336     r = MsiDatabaseOpenViewA(hdb, query, &hview);
337     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
338     r = MsiViewExecute(hview, 0);
339     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
340     r = MsiViewClose(hview);
341     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
342     r = MsiCloseHandle(hview);
343     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
344 
345     r = MsiViewFetch(hview2, &hrec);
346     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
347     r = MsiViewExecute(hview2, 0);
348     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
349     r = MsiViewFetch(hview2, &hrec);
350     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r);
351 
352     r = MsiCloseHandle(hrec);
353     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
354     r = MsiViewClose(hview2);
355     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
356     r = MsiCloseHandle(hview2);
357     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
358 
359     query = "SELECT * FROM `phone` WHERE `id` = 1";
360     r = do_query(hdb, query, &hrec);
361     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
362 
363     /* check the record contains what we put in it */
364     r = MsiRecordGetFieldCount(hrec);
365     ok(r == 3, "record count wrong\n");
366 
367     r = MsiRecordIsNull(hrec, 0);
368     ok(r == FALSE, "field 0 not null\n");
369 
370     r = MsiRecordGetInteger(hrec, 1);
371     ok(r == 1, "field 1 contents wrong\n");
372     sz = sizeof buf;
373     r = MsiRecordGetStringA(hrec, 2, buf, &sz);
374     ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
375     ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
376     sz = sizeof buf;
377     r = MsiRecordGetStringA(hrec, 3, buf, &sz);
378     ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
379     ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
380 
381     r = MsiCloseHandle(hrec);
382     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
383 
384     /* open a select query */
385     hrec = 100;
386     query = "SELECT * FROM `phone` WHERE `id` >= 10";
387     r = do_query(hdb, query, &hrec);
388     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
389     ok(hrec == 0, "hrec should be null\n");
390 
391     r = MsiCloseHandle(hrec);
392     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
393 
394     query = "SELECT * FROM `phone` WHERE `id` < 0";
395     r = do_query(hdb, query, &hrec);
396     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
397 
398     query = "SELECT * FROM `phone` WHERE `id` <= 0";
399     r = do_query(hdb, query, &hrec);
400     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
401 
402     query = "SELECT * FROM `phone` WHERE `id` <> 1";
403     r = do_query(hdb, query, &hrec);
404     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
405 
406     query = "SELECT * FROM `phone` WHERE `id` > 10";
407     r = do_query(hdb, query, &hrec);
408     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
409 
410     /* now try a few bad INSERT xqueries */
411     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
412         "VALUES(?, ?)";
413     r = MsiDatabaseOpenViewA(hdb, query, &hview);
414     ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
415 
416     /* construct a record to insert */
417     hrec = MsiCreateRecord(4);
418     r = MsiRecordSetInteger(hrec, 1, 2);
419     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
420     r = MsiRecordSetStringA(hrec, 2, "Adam");
421     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
422     r = MsiRecordSetStringA(hrec, 3, "96905305");
423     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
424 
425     /* insert another value, using a record and wildcards */
426     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
427         "VALUES(?, ?, ?)";
428     r = MsiDatabaseOpenViewA(hdb, query, &hview);
429     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
430 
431     if (r == ERROR_SUCCESS)
432     {
433         r = MsiViewExecute(hview, hrec);
434         ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
435         r = MsiViewClose(hview);
436         ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
437         r = MsiCloseHandle(hview);
438         ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
439     }
440     r = MsiCloseHandle(hrec);
441     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
442 
443     r = MsiViewFetch(0, NULL);
444     ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
445 
446     r = MsiDatabaseCommit(hdb);
447     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
448 
449     r = MsiCloseHandle(hdb);
450     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
451 
452     r = DeleteFileA(msifile);
453     ok(r == TRUE, "file didn't exist after commit\n");
454 }
455 
456 static void test_msidecomposedesc(void)
457 {
458     UINT (WINAPI *pMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
459     char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
460     const char *desc;
461     UINT r;
462     DWORD len;
463     HMODULE hmod;
464 
465     hmod = GetModuleHandleA("msi.dll");
466     pMsiDecomposeDescriptorA = (void*)GetProcAddress(hmod, "MsiDecomposeDescriptorA");
467     if (!pMsiDecomposeDescriptorA)
468         return;
469 
470     /* test a valid feature descriptor */
471     desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
472     len = 0;
473     prod[0] = feature[0] = comp[0] = 0;
474     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
475     ok(r == ERROR_SUCCESS, "returned an error\n");
476     ok(len == strlen(desc), "length was wrong\n");
477     ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
478     ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
479     ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
480 
481     /* test an invalid feature descriptor with too many characters */
482     desc = "']gAVn-}f(ZXfeAR6.ji"
483            "ThisWillFailIfTheresMoreThanAGuidsChars>"
484            "3w2x^IGfe?CxI5heAvk.";
485     len = 0;
486     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
487     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
488 
489     /* test a feature descriptor with < instead of > */
490     desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit<3w2x^IGfe?CxI5heAvk.";
491     len = 0;
492     prod[0] = feature[0] = 0;
493     comp[0] = 0x55;
494     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
495     ok(r == ERROR_SUCCESS, "returned an error\n");
496     ok(len == 41, "got %u\n", len);
497     ok(!strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}"), "got '%s'\n", prod);
498     ok(!strcmp(feature,"FollowTheWhiteRabbit"), "got '%s'\n", feature);
499     ok(!comp[0], "got '%s'\n", comp);
500 
501     len = 0;
502     prod[0] = feature[0] = 0;
503     comp[0] = 0x55;
504     r = pMsiDecomposeDescriptorA("yh1BVN)8A$!!!!!MKKSkAlwaysInstalledIntl_1033<", prod, feature, comp, &len);
505     ok(r == ERROR_SUCCESS, "got %u\n", r);
506     ok(len == 45, "got %u\n", len);
507     ok(!strcmp(prod, "{90150000-006E-0409-0000-0000000FF1CE}"), "got '%s'\n", prod);
508     ok(!strcmp(feature, "AlwaysInstalledIntl_1033"), "got '%s'\n", feature);
509     ok(!comp[0], "got '%s'\n", comp);
510 
511     /*
512      * Test a valid feature descriptor with the
513      * maximum number of characters and some trailing characters.
514      */
515     desc = "']gAVn-}f(ZXfeAR6.ji"
516            "ThisWillWorkIfTheresLTEThanAGuidsChars>"
517            "3w2x^IGfe?CxI5heAvk."
518            "extra";
519     len = 0;
520     r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
521     ok(r == ERROR_SUCCESS, "returned wrong error\n");
522     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
523 
524     len = 0;
525     r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
526     ok(r == ERROR_SUCCESS, "returned wrong error\n");
527     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
528 
529     len = 0;
530     r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
531     ok(r == ERROR_SUCCESS, "returned wrong error\n");
532     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
533 
534     len = 0;
535     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
536     ok(r == ERROR_SUCCESS, "returned wrong error\n");
537     ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
538 
539     len = 0;
540     r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
541     ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
542     ok(len == 0, "length wrong\n");
543 
544     r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL);
545     ok(r == ERROR_SUCCESS, "returned wrong error\n");
546 }
547 
548 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
549 {
550     MSIHANDLE htab = 0;
551     UINT res;
552 
553     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
554     if(res == ERROR_SUCCESS )
555     {
556         UINT r;
557 
558         r = MsiViewExecute( htab, hrec );
559         if(r != ERROR_SUCCESS )
560             res = r;
561 
562         r = MsiViewClose( htab );
563         if(r != ERROR_SUCCESS )
564             res = r;
565 
566         r = MsiCloseHandle( htab );
567         if(r != ERROR_SUCCESS )
568             res = r;
569     }
570     return res;
571 }
572 
573 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
574 {
575     return try_query_param( hdb, szQuery, 0 );
576 }
577 
578 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
579 {
580     MSIHANDLE hrec = 0;
581     UINT r;
582 
583     hrec = MsiCreateRecord( 1 );
584     MsiRecordSetStringA( hrec, 1, "Hello");
585 
586     r = try_query_param( hdb, szQuery, hrec );
587 
588     MsiCloseHandle( hrec );
589     return r;
590 }
591 
592 static void test_msibadqueries(void)
593 {
594     MSIHANDLE hdb = 0;
595     UINT r;
596 
597     DeleteFileA(msifile);
598 
599     /* just MsiOpenDatabase should not create a file */
600     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
601     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
602 
603     r = MsiDatabaseCommit( hdb );
604     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
605 
606     r = MsiCloseHandle( hdb );
607     ok(r == ERROR_SUCCESS , "Failed to close database\n");
608 
609     /* open it readonly */
610     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb );
611     ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
612 
613     /* add a table to it */
614     r = try_query( hdb, "select * from _Tables");
615     ok(r == ERROR_SUCCESS , "query 1 failed\n");
616 
617     r = MsiCloseHandle( hdb );
618     ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
619 
620     /* open it read/write */
621     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
622     ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
623 
624     /* a bunch of test queries that fail with the native MSI */
625 
626     r = try_query( hdb, "CREATE TABLE");
627     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
628 
629     r = try_query( hdb, "CREATE TABLE `a`");
630     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
631 
632     r = try_query( hdb, "CREATE TABLE `a` ()");
633     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
634 
635     r = try_query( hdb, "CREATE TABLE `a` (`b`)");
636     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
637 
638     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
639     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
640 
641     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
642     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
643 
644     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
645     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
646 
647     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
648     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
649 
650     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
651     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
652 
653     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
654     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
655 
656     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
657     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
658 
659     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
660     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
661 
662     r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
663     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
664 
665     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
666     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
667 
668     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
669     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
670 
671     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
672     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
673 
674     r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
675     ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
676 
677     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
678     ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
679 
680     r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
681     ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
682 
683     r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
684           "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
685     ok(r == ERROR_SUCCESS , "query 4 failed\n");
686 
687     r = MsiDatabaseCommit( hdb );
688     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
689 
690     r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
691                           "PRIMARY KEY `foo`)");
692     ok(r == ERROR_SUCCESS , "query 4 failed\n");
693 
694     r = try_insert_query( hdb, "insert into a  ( `b` ) VALUES ( ? )");
695     ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
696 
697     r = MsiDatabaseCommit( hdb );
698     ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
699 
700     r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
701                           "PRIMARY KEY `ba`)");
702     ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
703 
704     r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
705     ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
706 
707     r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
708                           "PRIMARY KEY `t`)");
709     ok(r == ERROR_SUCCESS , "query 7 failed\n");
710 
711     r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
712     ok(r == ERROR_SUCCESS , "query 8 failed\n");
713 
714     r = try_query( hdb, "select * from c");
715     ok(r == ERROR_SUCCESS , "query failed\n");
716 
717     r = try_query( hdb, "select * from c where b = 'x");
718     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
719 
720     r = try_query( hdb, "select * from c where b = 'x'");
721     ok(r == ERROR_SUCCESS, "query failed\n");
722 
723     r = try_query( hdb, "select * from 'c'");
724     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
725 
726     r = try_query( hdb, "select * from ''");
727     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
728 
729     r = try_query( hdb, "select * from c where b = x");
730     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
731 
732     r = try_query( hdb, "select * from c where b = \"x\"");
733     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
734 
735     r = try_query( hdb, "select * from c where b = 'x'");
736     ok(r == ERROR_SUCCESS, "query failed\n");
737 
738     r = try_query( hdb, "select * from c where b = '\"x'");
739     ok(r == ERROR_SUCCESS, "query failed\n");
740 
741     if (0)  /* FIXME: this query causes trouble with other tests */
742     {
743         r = try_query( hdb, "select * from c where b = '\\\'x'");
744         ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
745     }
746 
747     r = try_query( hdb, "select * from 'c'");
748     ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
749 
750     r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`");
751     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
752 
753     r = try_query( hdb, "select `c`.b` from `c`");
754     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
755 
756     r = try_query( hdb, "select `c`.`b from `c`");
757     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
758 
759     r = try_query( hdb, "select `c`.b from `c`");
760     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
761 
762     r = try_query( hdb, "select `c.`b` from `c`");
763     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
764 
765     r = try_query( hdb, "select c`.`b` from `c`");
766     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
767 
768     r = try_query( hdb, "select c.`b` from `c`");
769     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
770 
771     r = try_query( hdb, "select `c`.`b` from c`");
772     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
773 
774     r = try_query( hdb, "select `c`.`b` from `c");
775     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
776 
777     r = try_query( hdb, "select `c`.`b` from c");
778     ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
779 
780     r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
781     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
782 
783     r = try_query( hdb, "SELECT * FROM \5a" );
784     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
785 
786     r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
787     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
788 
789     r = try_query( hdb, "SELECT * FROM a\5" );
790     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
791 
792     r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
793     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
794 
795     r = try_query( hdb, "SELECT * FROM -a" );
796     todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
797 
798     r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
799     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
800 
801     r = try_query( hdb, "SELECT * FROM a-" );
802     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
803 
804     r = MsiCloseHandle( hdb );
805     ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
806 
807     r = DeleteFileA( msifile );
808     ok(r == TRUE, "file didn't exist after commit\n");
809 }
810 
811 static void test_viewmodify(void)
812 {
813     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
814     UINT r;
815     MSIDBERROR err;
816     const char *query;
817     char buffer[0x100];
818     DWORD sz;
819 
820     DeleteFileA(msifile);
821 
822     /* just MsiOpenDatabase should not create a file */
823     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
824     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
825 
826     query = "CREATE TABLE `phone` ( "
827             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
828             "PRIMARY KEY `id`)";
829     r = run_query( hdb, 0, query );
830     ok(r == ERROR_SUCCESS, "query failed\n");
831 
832     query = "CREATE TABLE `_Validation` ( "
833             "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
834             "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
835             "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
836             "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)";
837     r = run_query( hdb, 0, query );
838     ok(r == ERROR_SUCCESS, "query failed\n");
839 
840     query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) "
841             "VALUES('phone', 'id', 'N')";
842     r = run_query( hdb, 0, query );
843     ok(r == ERROR_SUCCESS, "query failed\n");
844 
845     /* check what the error function reports without doing anything */
846     sz = 0;
847     /* passing NULL as the 3rd param make function to crash on older platforms */
848     err = MsiViewGetErrorA( 0, NULL, &sz );
849     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
850 
851     /* open a view */
852     query = "SELECT * FROM `phone`";
853     r = MsiDatabaseOpenViewA(hdb, query, &hview);
854     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
855 
856     /* see what happens with a good hview and bad args */
857     err = MsiViewGetErrorA( hview, NULL, NULL );
858     ok(err == MSIDBERROR_INVALIDARG || err == MSIDBERROR_NOERROR,
859        "MsiViewGetError returns %u (expected -3)\n", err);
860     err = MsiViewGetErrorA( hview, buffer, NULL );
861     ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
862 
863     /* see what happens with a zero length buffer */
864     sz = 0;
865     buffer[0] = 'x';
866     err = MsiViewGetErrorA( hview, buffer, &sz );
867     ok(err == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
868     ok(buffer[0] == 'x', "buffer cleared\n");
869     ok(sz == 0, "size not zero\n");
870 
871     /* ok this one is strange */
872     sz = 0;
873     err = MsiViewGetErrorA( hview, NULL, &sz );
874     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
875     ok(sz == 0, "size not zero\n");
876 
877     /* see if it really has an error */
878     sz = sizeof buffer;
879     buffer[0] = 'x';
880     err = MsiViewGetErrorA( hview, buffer, &sz );
881     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
882     ok(buffer[0] == 0, "buffer not cleared\n");
883     ok(sz == 0, "size not zero\n");
884 
885     r = MsiViewExecute(hview, 0);
886     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
887 
888     /* try some invalid records */
889     r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
890     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
891     r = MsiViewModify(hview, -1, 0 );
892     ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
893 
894     /* try an small record */
895     hrec = MsiCreateRecord(1);
896     r = MsiViewModify(hview, -1, hrec );
897     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
898 
899     sz = sizeof buffer;
900     buffer[0] = 'x';
901     err = MsiViewGetErrorA( hview, buffer, &sz );
902     ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
903     ok(buffer[0] == 0, "buffer not cleared\n");
904     ok(sz == 0, "size not zero\n");
905 
906     r = MsiCloseHandle(hrec);
907     ok(r == ERROR_SUCCESS, "failed to close record\n");
908 
909     /* insert a valid record */
910     hrec = MsiCreateRecord(3);
911 
912     r = MsiRecordSetInteger(hrec, 1, 1);
913     ok(r == ERROR_SUCCESS, "failed to set integer\n");
914     r = MsiRecordSetStringA(hrec, 2, "bob");
915     ok(r == ERROR_SUCCESS, "failed to set string\n");
916     r = MsiRecordSetStringA(hrec, 3, "7654321");
917     ok(r == ERROR_SUCCESS, "failed to set string\n");
918 
919     r = MsiViewExecute(hview, 0);
920     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
921     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
922     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
923 
924     /* validate it */
925     r = MsiViewExecute(hview, 0);
926     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
927 
928     r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec );
929     ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r);
930 
931     sz = sizeof buffer;
932     buffer[0] = 'x';
933     err = MsiViewGetErrorA( hview, buffer, &sz );
934     ok(err == MSIDBERROR_DUPLICATEKEY, "MsiViewGetError returned %u\n", err);
935     ok(!strcmp(buffer, "id"), "expected \"id\" c, got \"%s\"\n", buffer);
936     ok(sz == 2, "size not 2\n");
937 
938     /* insert the same thing again */
939     r = MsiViewExecute(hview, 0);
940     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
941 
942     /* should fail ... */
943     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
944     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
945 
946     /* try to merge the same record */
947     r = MsiViewExecute(hview, 0);
948     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
949     r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
950     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
951 
952     r = MsiCloseHandle(hrec);
953     ok(r == ERROR_SUCCESS, "failed to close record\n");
954 
955     /* try merging a new record */
956     hrec = MsiCreateRecord(3);
957 
958     r = MsiRecordSetInteger(hrec, 1, 10);
959     ok(r == ERROR_SUCCESS, "failed to set integer\n");
960     r = MsiRecordSetStringA(hrec, 2, "pepe");
961     ok(r == ERROR_SUCCESS, "failed to set string\n");
962     r = MsiRecordSetStringA(hrec, 3, "7654321");
963     ok(r == ERROR_SUCCESS, "failed to set string\n");
964 
965     r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
966     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
967     r = MsiViewExecute(hview, 0);
968     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
969 
970     r = MsiCloseHandle(hrec);
971     ok(r == ERROR_SUCCESS, "failed to close record\n");
972 
973     r = MsiViewClose(hview);
974     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
975     r = MsiCloseHandle(hview);
976     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
977 
978     query = "SELECT * FROM `phone`";
979     r = MsiDatabaseOpenViewA(hdb, query, &hview);
980     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
981 
982     r = MsiViewExecute(hview, 0);
983     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
984 
985     r = MsiViewFetch(hview, &hrec);
986     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
987 
988     r = MsiRecordGetInteger(hrec, 1);
989     ok(r == 1, "Expected 1, got %d\n", r);
990 
991     sz = sizeof(buffer);
992     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
993     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
994     ok(!lstrcmpA(buffer, "bob"), "Expected bob, got %s\n", buffer);
995 
996     sz = sizeof(buffer);
997     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
998     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
999     ok(!lstrcmpA(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
1000 
1001     /* update the view, non-primary key */
1002     r = MsiRecordSetStringA(hrec, 3, "3141592");
1003     ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
1004 
1005     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1006     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1007 
1008     /* do it again */
1009     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1010     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
1011 
1012     /* update the view, primary key */
1013     r = MsiRecordSetInteger(hrec, 1, 5);
1014     ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
1015 
1016     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1017     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1018 
1019     r = MsiCloseHandle(hrec);
1020     ok(r == ERROR_SUCCESS, "failed to close record\n");
1021 
1022     r = MsiViewClose(hview);
1023     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1024     r = MsiCloseHandle(hview);
1025     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1026 
1027     query = "SELECT * FROM `phone`";
1028     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1029     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1030 
1031     r = MsiViewExecute(hview, 0);
1032     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1033 
1034     r = MsiViewFetch(hview, &hrec);
1035     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1036 
1037     r = MsiRecordGetInteger(hrec, 1);
1038     ok(r == 1, "Expected 1, got %d\n", r);
1039 
1040     sz = sizeof(buffer);
1041     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
1042     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1043     ok(!lstrcmpA(buffer, "bob"), "Expected bob, got %s\n", buffer);
1044 
1045     sz = sizeof(buffer);
1046     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
1047     ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1048     ok(!lstrcmpA(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
1049 
1050     r = MsiCloseHandle(hrec);
1051     ok(r == ERROR_SUCCESS, "failed to close record\n");
1052 
1053     /* use a record that doesn't come from a view fetch */
1054     hrec = MsiCreateRecord(3);
1055     ok(hrec != 0, "MsiCreateRecord failed\n");
1056 
1057     r = MsiRecordSetInteger(hrec, 1, 3);
1058     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1059     r = MsiRecordSetStringA(hrec, 2, "jane");
1060     ok(r == ERROR_SUCCESS, "failed to set string\n");
1061     r = MsiRecordSetStringA(hrec, 3, "112358");
1062     ok(r == ERROR_SUCCESS, "failed to set string\n");
1063 
1064     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1065     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
1066 
1067     r = MsiCloseHandle(hrec);
1068     ok(r == ERROR_SUCCESS, "failed to close record\n");
1069 
1070     /* use a record that doesn't come from a view fetch, primary key matches */
1071     hrec = MsiCreateRecord(3);
1072     ok(hrec != 0, "MsiCreateRecord failed\n");
1073 
1074     r = MsiRecordSetInteger(hrec, 1, 1);
1075     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1076     r = MsiRecordSetStringA(hrec, 2, "jane");
1077     ok(r == ERROR_SUCCESS, "failed to set string\n");
1078     r = MsiRecordSetStringA(hrec, 3, "112358");
1079     ok(r == ERROR_SUCCESS, "failed to set string\n");
1080 
1081     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1082     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1083 
1084     r = MsiCloseHandle(hrec);
1085     ok(r == ERROR_SUCCESS, "failed to close record\n");
1086 
1087     hrec = MsiCreateRecord(3);
1088 
1089     r = MsiRecordSetInteger(hrec, 1, 2);
1090     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1091     r = MsiRecordSetStringA(hrec, 2, "nick");
1092     ok(r == ERROR_SUCCESS, "failed to set string\n");
1093     r = MsiRecordSetStringA(hrec, 3, "141421");
1094     ok(r == ERROR_SUCCESS, "failed to set string\n");
1095 
1096     r = MsiViewExecute(hview, 0);
1097     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1098     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
1099     ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1100 
1101     r = MsiCloseHandle(hrec);
1102     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1103     r = MsiViewClose(hview);
1104     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1105     r = MsiCloseHandle(hview);
1106     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1107 
1108     query = "SELECT * FROM `phone` WHERE `id` = 1";
1109     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1110     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1111     r = MsiViewExecute(hview, 0);
1112     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1113     r = MsiViewFetch(hview, &hrec);
1114     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1115 
1116     /* change the id to match the second row */
1117     r = MsiRecordSetInteger(hrec, 1, 2);
1118     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1119     r = MsiRecordSetStringA(hrec, 2, "jerry");
1120     ok(r == ERROR_SUCCESS, "failed to set string\n");
1121 
1122     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1123     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1124 
1125     r = MsiCloseHandle(hrec);
1126     ok(r == ERROR_SUCCESS, "failed to close record\n");
1127     r = MsiViewClose(hview);
1128     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1129     r = MsiCloseHandle(hview);
1130     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1131 
1132     /* broader search */
1133     query = "SELECT * FROM `phone` ORDER BY `id`";
1134     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1135     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1136     r = MsiViewExecute(hview, 0);
1137     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1138     r = MsiViewFetch(hview, &hrec);
1139     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1140 
1141     /* change the id to match the second row */
1142     r = MsiRecordSetInteger(hrec, 1, 2);
1143     ok(r == ERROR_SUCCESS, "failed to set integer\n");
1144     r = MsiRecordSetStringA(hrec, 2, "jerry");
1145     ok(r == ERROR_SUCCESS, "failed to set string\n");
1146 
1147     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1148     ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1149 
1150     r = MsiCloseHandle(hrec);
1151     ok(r == ERROR_SUCCESS, "failed to close record\n");
1152     r = MsiViewClose(hview);
1153     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1154     r = MsiCloseHandle(hview);
1155     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1156 
1157     r = MsiCloseHandle( hdb );
1158     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1159 }
1160 
1161 static MSIHANDLE create_db(void)
1162 {
1163     MSIHANDLE hdb = 0;
1164     UINT res;
1165 
1166     DeleteFileW(msifileW);
1167 
1168     /* create an empty database */
1169     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1170     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1171     if( res != ERROR_SUCCESS )
1172         return hdb;
1173 
1174     res = MsiDatabaseCommit( hdb );
1175     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1176 
1177     return hdb;
1178 }
1179 
1180 static void test_getcolinfo(void)
1181 {
1182     MSIHANDLE hdb, hview = 0, rec = 0;
1183     UINT r;
1184     DWORD sz;
1185     char buffer[0x20];
1186 
1187     /* create an empty db */
1188     hdb = create_db();
1189     ok( hdb, "failed to create db\n");
1190 
1191     /* tables should be present */
1192     r = MsiDatabaseOpenViewA(hdb, "select * from _Tables", &hview);
1193     ok( r == ERROR_SUCCESS, "failed to open query\n");
1194 
1195     r = MsiViewExecute(hview, 0);
1196     ok( r == ERROR_SUCCESS, "failed to execute query\n");
1197 
1198     /* check that NAMES works */
1199     rec = 0;
1200     r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1201     ok( r == ERROR_SUCCESS, "failed to get names\n");
1202     sz = sizeof buffer;
1203     r = MsiRecordGetStringA(rec, 1, buffer, &sz );
1204     ok( r == ERROR_SUCCESS, "failed to get string\n");
1205     ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
1206     r = MsiCloseHandle( rec );
1207     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1208 
1209     /* check that TYPES works */
1210     rec = 0;
1211     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1212     ok( r == ERROR_SUCCESS, "failed to get names\n");
1213     sz = sizeof buffer;
1214     r = MsiRecordGetStringA(rec, 1, buffer, &sz );
1215     ok( r == ERROR_SUCCESS, "failed to get string\n");
1216     ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
1217     r = MsiCloseHandle( rec );
1218     ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1219 
1220     /* check that invalid values fail */
1221     rec = 0;
1222     r = MsiViewGetColumnInfo( hview, 100, &rec );
1223     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1224     ok( rec == 0, "returned a record\n");
1225 
1226     r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1227     ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1228 
1229     r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1230     ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1231 
1232     r = MsiViewClose(hview);
1233     ok( r == ERROR_SUCCESS, "failed to close view\n");
1234     r = MsiCloseHandle(hview);
1235     ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1236     r = MsiCloseHandle(hdb);
1237     ok( r == ERROR_SUCCESS, "failed to close database\n");
1238 }
1239 
1240 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1241 {
1242     MSIHANDLE hview = 0, rec = 0;
1243     UINT r;
1244 
1245     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1246     if( r != ERROR_SUCCESS )
1247         return r;
1248 
1249     r = MsiViewExecute(hview, 0);
1250     if( r == ERROR_SUCCESS )
1251     {
1252         MsiViewGetColumnInfo( hview, type, &rec );
1253     }
1254     MsiViewClose(hview);
1255     MsiCloseHandle(hview);
1256     return rec;
1257 }
1258 
1259 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1260 {
1261     MSIHANDLE hview = 0, rec = 0;
1262     UINT r, type = 0;
1263     char query[0x100];
1264 
1265     sprintf(query, "select * from `_Columns` where  `Table` = '%s'", table );
1266 
1267     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1268     if( r != ERROR_SUCCESS )
1269         return r;
1270 
1271     r = MsiViewExecute(hview, 0);
1272     if( r == ERROR_SUCCESS )
1273     {
1274         while (1)
1275         {
1276             r = MsiViewFetch( hview, &rec );
1277             if( r != ERROR_SUCCESS)
1278                 break;
1279             r = MsiRecordGetInteger( rec, 2 );
1280             if (r == field)
1281                 type = MsiRecordGetInteger( rec, 4 );
1282             MsiCloseHandle( rec );
1283         }
1284     }
1285     MsiViewClose(hview);
1286     MsiCloseHandle(hview);
1287     return type;
1288 }
1289 
1290 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
1291 {
1292     CHAR buffer[0x20];
1293     UINT r;
1294     DWORD sz;
1295 
1296     sz = sizeof buffer;
1297     r = MsiRecordGetStringA( rec, field, buffer, &sz );
1298     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1299 }
1300 
1301 static void test_viewgetcolumninfo(void)
1302 {
1303     MSIHANDLE hdb = 0, rec;
1304     UINT r;
1305 
1306     hdb = create_db();
1307     ok( hdb, "failed to create db\n");
1308 
1309     r = run_query( hdb, 0,
1310             "CREATE TABLE `Properties` "
1311             "( `Property` CHAR(255), "
1312             "  `Value` CHAR(1), "
1313             "  `Intvalue` INT, "
1314             "  `Integervalue` INTEGER, "
1315             "  `Shortvalue` SHORT, "
1316             "  `Longvalue` LONG, "
1317             "  `Longcharvalue` LONGCHAR, "
1318             "  `Charvalue` CHAR, "
1319             "  `Localizablevalue` CHAR LOCALIZABLE "
1320             "  PRIMARY KEY `Property`)" );
1321     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1322 
1323     /* check the column types */
1324     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1325     ok( rec, "failed to get column info record\n" );
1326 
1327     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1328     ok( check_record( rec, 2, "S1"), "wrong record type\n");
1329     ok( check_record( rec, 3, "I2"), "wrong record type\n");
1330     ok( check_record( rec, 4, "I2"), "wrong record type\n");
1331     ok( check_record( rec, 5, "I2"), "wrong record type\n");
1332     ok( check_record( rec, 6, "I4"), "wrong record type\n");
1333     ok( check_record( rec, 7, "S0"), "wrong record type\n");
1334     ok( check_record( rec, 8, "S0"), "wrong record type\n");
1335     ok( check_record( rec, 9, "L0"), "wrong record type\n");
1336 
1337     MsiCloseHandle( rec );
1338 
1339     /* check the type in _Columns */
1340     ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1341     ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1342     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1343     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1344     ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1345     ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1346     ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1347     ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 8 ), "_columns table wrong\n");
1348     ok( 0x1f00 == get_columns_table_type(hdb, "Properties", 9 ), "_columns table wrong\n");
1349 
1350     /* now try the names */
1351     rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1352     ok( rec, "failed to get column info record\n" );
1353 
1354     ok( check_record( rec, 1, "Property"), "wrong record type\n");
1355     ok( check_record( rec, 2, "Value"), "wrong record type\n");
1356     ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
1357     ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
1358     ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
1359     ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
1360     ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
1361     ok( check_record( rec, 8, "Charvalue"), "wrong record type\n");
1362     ok( check_record( rec, 9, "Localizablevalue"), "wrong record type\n");
1363 
1364     MsiCloseHandle( rec );
1365 
1366     r = run_query( hdb, 0,
1367             "CREATE TABLE `Binary` "
1368             "( `Name` CHAR(255), `Data` OBJECT  PRIMARY KEY `Name`)" );
1369     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1370 
1371     /* check the column types */
1372     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1373     ok( rec, "failed to get column info record\n" );
1374 
1375     ok( check_record( rec, 1, "S255"), "wrong record type\n");
1376     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1377 
1378     MsiCloseHandle( rec );
1379 
1380     /* check the type in _Columns */
1381     ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1382     ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1383 
1384     /* now try the names */
1385     rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1386     ok( rec, "failed to get column info record\n" );
1387 
1388     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1389     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1390     MsiCloseHandle( rec );
1391 
1392     r = run_query( hdb, 0,
1393             "CREATE TABLE `UIText` "
1394             "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1395     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1396 
1397     ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1398     ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1399 
1400     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1401     ok( rec, "failed to get column info record\n" );
1402     ok( check_record( rec, 1, "Key"), "wrong record type\n");
1403     ok( check_record( rec, 2, "Text"), "wrong record type\n");
1404     MsiCloseHandle( rec );
1405 
1406     rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1407     ok( rec, "failed to get column info record\n" );
1408     ok( check_record( rec, 1, "s72"), "wrong record type\n");
1409     ok( check_record( rec, 2, "L255"), "wrong record type\n");
1410     MsiCloseHandle( rec );
1411 
1412     MsiCloseHandle( hdb );
1413 }
1414 
1415 static void test_msiexport(void)
1416 {
1417     MSIHANDLE hdb = 0, hview = 0;
1418     UINT r;
1419     const char *query;
1420     char path[MAX_PATH];
1421     const char file[] = "phone.txt";
1422     HANDLE handle;
1423     char buffer[0x100];
1424     DWORD length;
1425     const char expected[] =
1426         "id\tname\tnumber\r\n"
1427         "I2\tS32\tS32\r\n"
1428         "phone\tid\r\n"
1429         "1\tAbe\t8675309\r\n";
1430 
1431     DeleteFileW(msifileW);
1432 
1433     /* just MsiOpenDatabase should not create a file */
1434     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1435     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1436 
1437     /* create a table */
1438     query = "CREATE TABLE `phone` ( "
1439             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1440             "PRIMARY KEY `id`)";
1441     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1442     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1443     r = MsiViewExecute(hview, 0);
1444     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1445     r = MsiViewClose(hview);
1446     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1447     r = MsiCloseHandle(hview);
1448     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1449 
1450     /* insert a value into it */
1451     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1452         "VALUES('1', 'Abe', '8675309')";
1453     r = MsiDatabaseOpenViewA(hdb, query, &hview);
1454     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1455     r = MsiViewExecute(hview, 0);
1456     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1457     r = MsiViewClose(hview);
1458     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1459     r = MsiCloseHandle(hview);
1460     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1461 
1462     GetCurrentDirectoryA(MAX_PATH, path);
1463 
1464     r = MsiDatabaseExportA(hdb, "phone", path, file);
1465     ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1466 
1467     MsiCloseHandle(hdb);
1468 
1469     lstrcatA(path, "\\");
1470     lstrcatA(path, file);
1471 
1472     /* check the data that was written */
1473     length = 0;
1474     memset(buffer, 0, sizeof buffer);
1475     handle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1476     if (handle != INVALID_HANDLE_VALUE)
1477     {
1478         ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1479         CloseHandle(handle);
1480         DeleteFileA(path);
1481     }
1482     else
1483         ok(0, "failed to open file %s\n", path);
1484 
1485     ok( length == strlen(expected), "length of data wrong\n");
1486     ok( !lstrcmpA(buffer, expected), "data doesn't match\n");
1487     DeleteFileA(msifile);
1488 }
1489 
1490 static void test_longstrings(void)
1491 {
1492     const char insert_query[] =
1493         "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1494     char *str;
1495     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1496     DWORD len;
1497     UINT r;
1498     const DWORD STRING_LENGTH = 0x10005;
1499 
1500     DeleteFileW(msifileW);
1501     /* just MsiOpenDatabase should not create a file */
1502     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1503     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1504 
1505     /* create a table */
1506     r = try_query( hdb,
1507         "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1508     ok(r == ERROR_SUCCESS, "query failed\n");
1509 
1510     /* try to insert a very long string */
1511     str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
1512     len = strchr(insert_query, 'Z') - insert_query;
1513     strcpy(str, insert_query);
1514     memset(str+len, 'Z', STRING_LENGTH);
1515     strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1516     r = try_query( hdb, str );
1517     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1518 
1519     HeapFree(GetProcessHeap(), 0, str);
1520 
1521     r = MsiDatabaseCommit(hdb);
1522     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1523     MsiCloseHandle(hdb);
1524 
1525     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
1526     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1527 
1528     r = MsiDatabaseOpenViewA(hdb, "select * from `strings` where `id` = 1", &hview);
1529     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1530 
1531     r = MsiViewExecute(hview, 0);
1532     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1533 
1534     r = MsiViewFetch(hview, &hrec);
1535     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1536 
1537     MsiViewClose(hview);
1538     MsiCloseHandle(hview);
1539 
1540     r = MsiRecordGetStringA(hrec, 2, NULL, &len);
1541     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1542     ok(len == STRING_LENGTH, "string length wrong\n");
1543 
1544     MsiCloseHandle(hrec);
1545     MsiCloseHandle(hdb);
1546     DeleteFileA(msifile);
1547 }
1548 
1549 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1550 {
1551     HANDLE file;
1552     DWORD written;
1553 
1554     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1555     if (file == INVALID_HANDLE_VALUE)
1556         return;
1557 
1558     WriteFile(file, data, strlen(data), &written, NULL);
1559     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1560 
1561     if (size)
1562     {
1563         SetFilePointer(file, size, NULL, FILE_BEGIN);
1564         SetEndOfFile(file);
1565     }
1566 
1567     CloseHandle(file);
1568 }
1569 
1570 #define create_file(name) create_file_data(name, name, 0)
1571 
1572 static void test_streamtable(void)
1573 {
1574     MSIHANDLE hdb = 0, rec, view, hsi;
1575     char file[MAX_PATH];
1576     char buf[MAX_PATH];
1577     DWORD size;
1578     UINT r;
1579 
1580     hdb = create_db();
1581     ok( hdb, "failed to create db\n");
1582 
1583     r = run_query( hdb, 0,
1584             "CREATE TABLE `Properties` "
1585             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
1586     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1587 
1588     r = run_query( hdb, 0,
1589             "INSERT INTO `Properties` "
1590             "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1591     ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1592 
1593     r = MsiDatabaseCommit( hdb );
1594     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1595 
1596     MsiCloseHandle( hdb );
1597 
1598     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
1599     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1600 
1601     /* check the column types */
1602     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1603     ok( rec, "failed to get column info record\n" );
1604 
1605     ok( check_record( rec, 1, "s62"), "wrong record type\n");
1606     ok( check_record( rec, 2, "V0"), "wrong record type\n");
1607 
1608     MsiCloseHandle( rec );
1609 
1610     /* now try the names */
1611     rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1612     ok( rec, "failed to get column info record\n" );
1613 
1614     ok( check_record( rec, 1, "Name"), "wrong record type\n");
1615     ok( check_record( rec, 2, "Data"), "wrong record type\n");
1616 
1617     MsiCloseHandle( rec );
1618 
1619     r = MsiDatabaseOpenViewA( hdb,
1620             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1621     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1622 
1623     r = MsiViewExecute( view, 0 );
1624     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1625 
1626     r = MsiViewFetch( view, &rec );
1627     ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1628 
1629     MsiCloseHandle( rec );
1630     MsiViewClose( view );
1631     MsiCloseHandle( view );
1632 
1633     /* create a summary information stream */
1634     r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1635     ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1636 
1637     r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1638     ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1639 
1640     r = MsiSummaryInfoPersist( hsi );
1641     ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1642 
1643     MsiCloseHandle( hsi );
1644 
1645     r = MsiDatabaseOpenViewA( hdb,
1646             "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1647     ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1648 
1649     r = MsiViewExecute( view, 0 );
1650     ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1651 
1652     r = MsiViewFetch( view, &rec );
1653     ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1654 
1655     MsiCloseHandle( rec );
1656     MsiViewClose( view );
1657     MsiCloseHandle( view );
1658 
1659     /* insert a file into the _Streams table */
1660     create_file( "test.txt" );
1661 
1662     rec = MsiCreateRecord( 2 );
1663     MsiRecordSetStringA( rec, 1, "data" );
1664 
1665     r = MsiRecordSetStreamA( rec, 2, "test.txt" );
1666     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1667 
1668     DeleteFileA("test.txt");
1669 
1670     r = MsiDatabaseOpenViewA( hdb,
1671             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1672     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1673 
1674     r = MsiViewExecute( view, rec );
1675     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1676 
1677     MsiCloseHandle( rec );
1678     MsiViewClose( view );
1679     MsiCloseHandle( view );
1680 
1681     /* insert another one */
1682     create_file( "test1.txt" );
1683 
1684     rec = MsiCreateRecord( 2 );
1685     MsiRecordSetStringA( rec, 1, "data1" );
1686 
1687     r = MsiRecordSetStreamA( rec, 2, "test1.txt" );
1688     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1689 
1690     DeleteFileA("test1.txt");
1691 
1692     r = MsiDatabaseOpenViewA( hdb,
1693             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1694     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1695 
1696     r = MsiViewExecute( view, rec );
1697     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1698 
1699     MsiCloseHandle( rec );
1700     MsiViewClose( view );
1701     MsiCloseHandle( view );
1702 
1703     /* try again */
1704     create_file( "test1.txt" );
1705 
1706     rec = MsiCreateRecord( 2 );
1707     MsiRecordSetStringA( rec, 1, "data1" );
1708 
1709     r = MsiRecordSetStreamA( rec, 2, "test1.txt" );
1710     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r );
1711 
1712     DeleteFileA( "test1.txt" );
1713 
1714     r = MsiDatabaseOpenViewA( hdb,
1715             "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1716     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r );
1717 
1718     r = MsiViewExecute( view, rec );
1719     ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r );
1720 
1721     MsiCloseHandle( rec );
1722     MsiViewClose( view );
1723     MsiCloseHandle( view );
1724 
1725     r = MsiDatabaseOpenViewA( hdb,
1726             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1727     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1728 
1729     r = MsiViewExecute( view, 0 );
1730     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1731 
1732     r = MsiViewFetch( view, &rec );
1733     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1734 
1735     size = MAX_PATH;
1736     r = MsiRecordGetStringA( rec, 1, file, &size );
1737     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1738     ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file);
1739 
1740     size = MAX_PATH;
1741     memset(buf, 0, MAX_PATH);
1742     r = MsiRecordReadStream( rec, 2, buf, &size );
1743     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1744     ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf);
1745 
1746     MsiCloseHandle( rec );
1747     MsiViewClose( view );
1748     MsiCloseHandle( view );
1749 
1750     r = MsiDatabaseOpenViewA( hdb,
1751             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1752     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1753 
1754     r = MsiViewExecute( view, 0 );
1755     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1756 
1757     r = MsiViewFetch( view, &rec );
1758     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1759 
1760     size = MAX_PATH;
1761     r = MsiRecordGetStringA( rec, 1, file, &size );
1762     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1763     ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file);
1764 
1765     size = MAX_PATH;
1766     memset(buf, 0, MAX_PATH);
1767     r = MsiRecordReadStream( rec, 2, buf, &size );
1768     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1769     ok( !lstrcmpA(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
1770 
1771     MsiCloseHandle( rec );
1772     MsiViewClose( view );
1773     MsiCloseHandle( view );
1774 
1775     /* perform an update */
1776     create_file( "test2.txt" );
1777     rec = MsiCreateRecord( 1 );
1778 
1779     r = MsiRecordSetStreamA( rec, 1, "test2.txt" );
1780     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1781 
1782     DeleteFileA("test2.txt");
1783 
1784     r = MsiDatabaseOpenViewA( hdb,
1785             "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1786     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1787 
1788     r = MsiViewExecute( view, rec );
1789     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1790 
1791     MsiCloseHandle( rec );
1792     MsiViewClose( view );
1793     MsiCloseHandle( view );
1794 
1795     r = MsiDatabaseOpenViewA( hdb,
1796             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1797     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1798 
1799     r = MsiViewExecute( view, 0 );
1800     ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1801 
1802     r = MsiViewFetch( view, &rec );
1803     ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1804 
1805     size = MAX_PATH;
1806     r = MsiRecordGetStringA( rec, 1, file, &size );
1807     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1808     ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file);
1809 
1810     size = MAX_PATH;
1811     memset(buf, 0, MAX_PATH);
1812     r = MsiRecordReadStream( rec, 2, buf, &size );
1813     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1814     ok( !lstrcmpA(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
1815 
1816     MsiCloseHandle( rec );
1817     MsiViewClose( view );
1818     MsiCloseHandle( view );
1819     MsiCloseHandle( hdb );
1820     DeleteFileA(msifile);
1821 }
1822 
1823 static void test_binary(void)
1824 {
1825     MSIHANDLE hdb = 0, rec;
1826     char file[MAX_PATH];
1827     char buf[MAX_PATH];
1828     DWORD size;
1829     LPCSTR query;
1830     UINT r;
1831 
1832     /* insert a file into the Binary table */
1833     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1834     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1835 
1836     query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
1837     r = run_query( hdb, 0, query );
1838     ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1839 
1840     create_file( "test.txt" );
1841     rec = MsiCreateRecord( 1 );
1842     r = MsiRecordSetStreamA( rec, 1, "test.txt" );
1843     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1844     DeleteFileA( "test.txt" );
1845 
1846     /* try a name that exceeds maximum OLE stream name length */
1847     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'encryption.dll.CB4E6205_F99A_4C51_ADD4_184506EFAB87', 10000, ? )";
1848     r = run_query( hdb, rec, query );
1849     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1850 
1851     r = MsiCloseHandle( rec );
1852     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1853 
1854     r = MsiDatabaseCommit( hdb );
1855     ok( r == ERROR_FUNCTION_FAILED , "got %u\n", r );
1856 
1857     r = MsiCloseHandle( hdb );
1858     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1859 
1860     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1861     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1862 
1863     query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
1864     r = run_query( hdb, 0, query );
1865     ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1866 
1867     create_file( "test.txt" );
1868     rec = MsiCreateRecord( 1 );
1869     r = MsiRecordSetStreamA( rec, 1, "test.txt" );
1870     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r );
1871     DeleteFileA( "test.txt" );
1872 
1873     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1874     r = run_query( hdb, rec, query );
1875     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1876 
1877     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1878     r = run_query( hdb, rec, query );
1879     ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r );
1880 
1881     r = MsiCloseHandle( rec );
1882     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1883 
1884     r = MsiDatabaseCommit( hdb );
1885     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1886 
1887     r = MsiCloseHandle( hdb );
1888     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1889 
1890     /* read file from the Stream table */
1891     r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb );
1892     ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1893 
1894     query = "SELECT * FROM `_Streams`";
1895     r = do_query( hdb, query, &rec );
1896     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1897 
1898     size = MAX_PATH;
1899     r = MsiRecordGetStringA( rec, 1, file, &size );
1900     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1901     ok( !lstrcmpA(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1902 
1903     size = MAX_PATH;
1904     memset( buf, 0, MAX_PATH );
1905     r = MsiRecordReadStream( rec, 2, buf, &size );
1906     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1907     ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1908 
1909     r = MsiCloseHandle( rec );
1910     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1911 
1912     /* read file from the Binary table */
1913     query = "SELECT * FROM `Binary`";
1914     r = do_query( hdb, query, &rec );
1915     ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1916 
1917     size = MAX_PATH;
1918     r = MsiRecordGetStringA( rec, 1, file, &size );
1919     ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1920     ok( !lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file );
1921 
1922     size = MAX_PATH;
1923     memset( buf, 0, MAX_PATH );
1924     r = MsiRecordReadStream( rec, 3, buf, &size );
1925     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1926     ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1927 
1928     r = MsiCloseHandle( rec );
1929     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1930 
1931     r = MsiCloseHandle( hdb );
1932     ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1933 
1934     DeleteFileA( msifile );
1935 }
1936 
1937 static void test_where_not_in_selected(void)
1938 {
1939     MSIHANDLE hdb = 0, rec, view;
1940     LPCSTR query;
1941     UINT r;
1942 
1943     hdb = create_db();
1944     ok( hdb, "failed to create db\n");
1945 
1946     r = run_query(hdb, 0,
1947             "CREATE TABLE `IESTable` ("
1948             "`Action` CHAR(64), "
1949             "`Condition` CHAR(64), "
1950             "`Sequence` LONG PRIMARY KEY `Sequence`)");
1951     ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1952 
1953     r = run_query(hdb, 0,
1954             "CREATE TABLE `CATable` ("
1955             "`Action` CHAR(64), "
1956             "`Type` LONG PRIMARY KEY `Type`)");
1957     ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1958 
1959     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1960             "( `Action`, `Condition`, `Sequence`) "
1961             "VALUES ( 'clean', 'cond4', 4)");
1962     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1963 
1964     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1965             "( `Action`, `Condition`, `Sequence`) "
1966             "VALUES ( 'depends', 'cond1', 1)");
1967     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1968 
1969     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1970             "( `Action`, `Condition`, `Sequence`) "
1971             "VALUES ( 'build', 'cond2', 2)");
1972     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1973 
1974     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1975             "( `Action`, `Condition`, `Sequence`) "
1976             "VALUES ( 'build2', 'cond6', 6)");
1977     ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1978 
1979     r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1980             "( `Action`, `Condition`, `Sequence`) "
1981             "VALUES ( 'build', 'cond3', 3)");
1982     ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1983 
1984     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1985             "( `Action`, `Type` ) "
1986             "VALUES ( 'build', 32)");
1987     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1988 
1989     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1990             "( `Action`, `Type` ) "
1991             "VALUES ( 'depends', 64)");
1992     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1993 
1994     r = run_query(hdb, 0, "INSERT INTO `CATable` "
1995             "( `Action`, `Type` ) "
1996             "VALUES ( 'clean', 63)");
1997     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1998 
1999     r = run_query(hdb, 0, "INSERT INTO `CATable` "
2000             "( `Action`, `Type` ) "
2001             "VALUES ( 'build2', 34)");
2002     ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
2003     query = "Select IESTable.Condition from CATable, IESTable where "
2004             "CATable.Action = IESTable.Action and CATable.Type = 32";
2005     r = MsiDatabaseOpenViewA(hdb, query, &view);
2006     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
2007 
2008     r = MsiViewExecute(view, 0);
2009     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
2010 
2011     r = MsiViewFetch(view, &rec);
2012     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2013 
2014     ok( check_record( rec, 1, "cond2"), "wrong condition\n");
2015 
2016     MsiCloseHandle( rec );
2017     r = MsiViewFetch(view, &rec);
2018     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2019 
2020     ok( check_record( rec, 1, "cond3"), "wrong condition\n");
2021 
2022     MsiCloseHandle( rec );
2023     MsiViewClose(view);
2024     MsiCloseHandle(view);
2025 
2026     MsiCloseHandle( hdb );
2027     DeleteFileA(msifile);
2028 }
2029 
2030 
2031 static void test_where(void)
2032 {
2033     MSIHANDLE hdb = 0, rec, view;
2034     LPCSTR query;
2035     UINT r;
2036     DWORD size;
2037     CHAR buf[MAX_PATH];
2038     UINT count;
2039 
2040     hdb = create_db();
2041     ok( hdb, "failed to create db\n");
2042 
2043     r = run_query( hdb, 0,
2044             "CREATE TABLE `Media` ("
2045             "`DiskId` SHORT NOT NULL, "
2046             "`LastSequence` LONG, "
2047             "`DiskPrompt` CHAR(64) LOCALIZABLE, "
2048             "`Cabinet` CHAR(255), "
2049             "`VolumeLabel` CHAR(32), "
2050             "`Source` CHAR(72) "
2051             "PRIMARY KEY `DiskId`)" );
2052     ok( r == S_OK, "cannot create Media table: %d\n", r );
2053 
2054     r = run_query( hdb, 0, "INSERT INTO `Media` "
2055             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
2056             "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
2057     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
2058 
2059     r = run_query( hdb, 0, "INSERT INTO `Media` "
2060             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
2061             "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
2062     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
2063 
2064     r = run_query( hdb, 0, "INSERT INTO `Media` "
2065             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
2066             "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
2067     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
2068 
2069     query = "SELECT * FROM `Media`";
2070     r = do_query(hdb, query, &rec);
2071     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
2072     ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
2073     MsiCloseHandle( rec );
2074 
2075     query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
2076     r = do_query(hdb, query, &rec);
2077     ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
2078     ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
2079 
2080     r = MsiRecordGetInteger(rec, 1);
2081     ok( 2 == r, "field wrong\n");
2082     r = MsiRecordGetInteger(rec, 2);
2083     ok( 1 == r, "field wrong\n");
2084     MsiCloseHandle( rec );
2085 
2086     query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
2087     r = MsiDatabaseOpenViewA(hdb, query, &view);
2088     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
2089 
2090     r = MsiViewExecute(view, 0);
2091     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
2092 
2093     r = MsiViewFetch(view, &rec);
2094     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2095 
2096     count = MsiRecordGetFieldCount( rec );
2097     ok( count == 1, "Expected 1 record fields, got %d\n", count );
2098 
2099     size = MAX_PATH;
2100     r = MsiRecordGetStringA( rec, 1, buf, &size );
2101     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2102     ok( !lstrcmpA( buf, "2" ), "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
2103     MsiCloseHandle( rec );
2104 
2105     r = MsiViewFetch(view, &rec);
2106     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2107 
2108     size = MAX_PATH;
2109     r = MsiRecordGetStringA( rec, 1, buf, &size );
2110     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2111     ok( !lstrcmpA( buf, "3" ), "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
2112     MsiCloseHandle( rec );
2113 
2114     r = MsiViewFetch(view, &rec);
2115     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
2116 
2117     MsiViewClose(view);
2118     MsiCloseHandle(view);
2119 
2120     MsiCloseHandle( rec );
2121 
2122     rec = 0;
2123     query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
2124     r = do_query(hdb, query, &rec);
2125     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2126     MsiCloseHandle( rec );
2127 
2128     rec = 0;
2129     query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
2130     r = do_query(hdb, query, &rec);
2131     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2132     MsiCloseHandle( rec );
2133 
2134     rec = 0;
2135     query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
2136     r = do_query(hdb, query, &rec);
2137     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2138     MsiCloseHandle( rec );
2139 
2140     rec = 0;
2141     query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
2142     r = do_query(hdb, query, &rec);
2143     ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2144     MsiCloseHandle( rec );
2145 
2146     rec = 0;
2147     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
2148     r = do_query(hdb, query, &rec);
2149     ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
2150     MsiCloseHandle( rec );
2151 
2152     rec = MsiCreateRecord(1);
2153     MsiRecordSetStringA(rec, 1, "");
2154 
2155     query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
2156     r = MsiDatabaseOpenViewA(hdb, query, &view);
2157     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2158     r = MsiViewExecute(view, rec);
2159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2160 
2161     MsiCloseHandle(rec);
2162 
2163     r = MsiViewFetch(view, &rec);
2164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2165 
2166     MsiCloseHandle(rec);
2167     MsiViewClose(view);
2168     MsiCloseHandle(view);
2169 
2170     MsiCloseHandle( hdb );
2171     DeleteFileA(msifile);
2172 }
2173 
2174 static CHAR CURR_DIR[MAX_PATH];
2175 
2176 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
2177                                 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
2178                                 "TestTable\tFirstPrimaryColumn\n"
2179                                 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
2180 
2181 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
2182                                   "s255\ts255\n"
2183                                   "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
2184                                   "papaya\tleaf\n"
2185                                   "papaya\tflower\n";
2186 
2187 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
2188                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2189                                 "Table\tA\r\n"
2190                                 "a\tb\tc\td\te\tf\n"
2191                                 "g\th\ti\t\rj\tk\tl\r\n";
2192 
2193 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
2194                                 "s72\ts72\ts72\ts72\ts72\ts72\n"
2195                                 "Table2\tA\r\n"
2196                                 "a\tb\tc\td\te\tf\n"
2197                                 "g\th\ti\tj\tk\tl\r\n";
2198 
2199 static const CHAR suminfo[] = "PropertyId\tValue\n"
2200                               "i2\tl255\n"
2201                               "_SummaryInformation\tPropertyId\n"
2202                               "1\t1252\n"
2203                               "2\tInstaller Database\n"
2204                               "3\tInstaller description\n"
2205                               "4\tWineHQ\n"
2206                               "5\tInstaller\n"
2207                               "6\tInstaller comments\n"
2208                               "7\tIntel;1033,2057\n"
2209                               "9\t{12345678-1234-1234-1234-123456789012}\n"
2210                               "12\t2009/04/12 15:46:11\n"
2211                               "13\t2009/04/12 15:46:11\n"
2212                               "14\t200\n"
2213                               "15\t2\n"
2214                               "18\tVim\n"
2215                               "19\t2\n";
2216 
2217 static void write_file(const CHAR *filename, const char *data, int data_size)
2218 {
2219     DWORD size;
2220 
2221     HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
2222                             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2223     WriteFile(hf, data, data_size, &size, NULL);
2224     CloseHandle(hf);
2225 }
2226 
2227 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2228 {
2229     UINT r;
2230 
2231     write_file("temp_file", table_data, (lstrlenA(table_data) - 1) * sizeof(char));
2232     r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2233     DeleteFileA("temp_file");
2234 
2235     return r;
2236 }
2237 
2238 static void test_suminfo_import(void)
2239 {
2240     MSIHANDLE hdb, hsi, view = 0;
2241     LPCSTR query;
2242     UINT r, count, size, type;
2243     char str_value[50];
2244     INT int_value;
2245     FILETIME ft_value;
2246 
2247     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2248 
2249     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2251 
2252     r = add_table_to_db(hdb, suminfo);
2253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2254 
2255     /* _SummaryInformation is not imported as a regular table... */
2256 
2257     query = "SELECT * FROM `_SummaryInformation`";
2258     r = MsiDatabaseOpenViewA(hdb, query, &view);
2259     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2260     MsiCloseHandle(view);
2261 
2262     /* ...its data is added to the special summary information stream */
2263 
2264     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2266 
2267     r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2269     ok(count == 14, "Expected 14, got %u\n", count);
2270 
2271     r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2273     ok(type ==  VT_I2, "Expected VT_I2, got %u\n", type);
2274     ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2275 
2276     size = sizeof(str_value);
2277     r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2279     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2280     ok(size == 18, "Expected 18, got %u\n", size);
2281     ok(!strcmp(str_value, "Installer Database"),
2282        "Expected \"Installer Database\", got %s\n", str_value);
2283 
2284     size = sizeof(str_value);
2285     r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2287     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2288     ok(!strcmp(str_value, "Installer description"),
2289        "Expected \"Installer description\", got %s\n", str_value);
2290 
2291     size = sizeof(str_value);
2292     r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2294     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2295     ok(!strcmp(str_value, "WineHQ"),
2296        "Expected \"WineHQ\", got %s\n", str_value);
2297 
2298     size = sizeof(str_value);
2299     r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2301     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2302     ok(!strcmp(str_value, "Installer"),
2303        "Expected \"Installer\", got %s\n", str_value);
2304 
2305     size = sizeof(str_value);
2306     r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2308     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2309     ok(!strcmp(str_value, "Installer comments"),
2310        "Expected \"Installer comments\", got %s\n", str_value);
2311 
2312     size = sizeof(str_value);
2313     r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2315     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2316     ok(!strcmp(str_value, "Intel;1033,2057"),
2317        "Expected \"Intel;1033,2057\", got %s\n", str_value);
2318 
2319     size = sizeof(str_value);
2320     r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2322     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2323     ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2324        "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2325 
2326     r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2328     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2329 
2330     r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2332     ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2333 
2334     r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2336     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2337     ok(int_value == 200, "Expected 200, got %d\n", int_value);
2338 
2339     r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2341     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2342     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2343 
2344     r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2346     ok(type ==  VT_I4, "Expected VT_I4, got %u\n", type);
2347     ok(int_value == 2, "Expected 2, got %d\n", int_value);
2348 
2349     size = sizeof(str_value);
2350     r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2352     ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2353     ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2354 
2355     MsiCloseHandle(hsi);
2356     MsiCloseHandle(hdb);
2357     DeleteFileA(msifile);
2358 }
2359 
2360 static void test_msiimport(void)
2361 {
2362     MSIHANDLE hdb, view, rec;
2363     LPCSTR query;
2364     UINT r, count;
2365     signed int i;
2366 
2367     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2368 
2369     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2371 
2372     r = add_table_to_db(hdb, test_data);
2373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2374 
2375     r = add_table_to_db(hdb, two_primary);
2376     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2377 
2378     r = add_table_to_db(hdb, endlines1);
2379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2380 
2381     r = add_table_to_db(hdb, endlines2);
2382     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2383 
2384     query = "SELECT * FROM `TestTable`";
2385     r = MsiDatabaseOpenViewA(hdb, query, &view);
2386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2387 
2388     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2390     count = MsiRecordGetFieldCount(rec);
2391     ok(count == 9, "Expected 9, got %d\n", count);
2392     ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2393     ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2394     ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2395     ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2396     ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2397     ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2398     ok(check_record(rec, 7, "String"), "Expected String\n");
2399     ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2400     ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2401     MsiCloseHandle(rec);
2402 
2403     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2405     count = MsiRecordGetFieldCount(rec);
2406     ok(count == 9, "Expected 9, got %d\n", count);
2407     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2408     ok(check_record(rec, 2, "i2"), "Expected i2\n");
2409     ok(check_record(rec, 3, "i2"), "Expected i2\n");
2410     ok(check_record(rec, 4, "I2"), "Expected I2\n");
2411     ok(check_record(rec, 5, "i4"), "Expected i4\n");
2412     ok(check_record(rec, 6, "I4"), "Expected I4\n");
2413     ok(check_record(rec, 7, "S255"), "Expected S255\n");
2414     ok(check_record(rec, 8, "S0"), "Expected S0\n");
2415     ok(check_record(rec, 9, "s0"), "Expected s0\n");
2416     MsiCloseHandle(rec);
2417 
2418     query = "SELECT * FROM `TestTable`";
2419     r = do_query(hdb, query, &rec);
2420     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2421     ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2422     ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2423     ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2424     ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2425 
2426     i = MsiRecordGetInteger(rec, 2);
2427     ok(i == 5, "Expected 5, got %d\n", i);
2428 
2429     i = MsiRecordGetInteger(rec, 3);
2430     ok(i == 2, "Expected 2, got %d\n", i);
2431 
2432     i = MsiRecordGetInteger(rec, 4);
2433     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2434 
2435     i = MsiRecordGetInteger(rec, 5);
2436     ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2437 
2438     i = MsiRecordGetInteger(rec, 6);
2439     ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2440 
2441     MsiCloseHandle(rec);
2442     MsiViewClose(view);
2443     MsiCloseHandle(view);
2444 
2445     query = "SELECT * FROM `TwoPrimary`";
2446     r = MsiDatabaseOpenViewA(hdb, query, &view);
2447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2448 
2449     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2451     count = MsiRecordGetFieldCount(rec);
2452     ok(count == 2, "Expected 2, got %d\n", count);
2453     ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2454     ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2455 
2456     MsiCloseHandle(rec);
2457 
2458     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2459     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2460     count = MsiRecordGetFieldCount(rec);
2461     ok(count == 2, "Expected 2, got %d\n", count);
2462     ok(check_record(rec, 1, "s255"), "Expected s255\n");
2463     ok(check_record(rec, 2, "s255"), "Expected s255\n");
2464     MsiCloseHandle(rec);
2465 
2466     r = MsiViewExecute(view, 0);
2467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2468 
2469     r = MsiViewFetch(view, &rec);
2470     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2471 
2472     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2473     ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2474 
2475     MsiCloseHandle(rec);
2476 
2477     r = MsiViewFetch(view, &rec);
2478     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2479 
2480     ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2481     ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2482 
2483     MsiCloseHandle(rec);
2484 
2485     r = MsiViewFetch(view, &rec);
2486     ok(r == ERROR_NO_MORE_ITEMS,
2487        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2488 
2489     r = MsiViewClose(view);
2490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2491 
2492     MsiCloseHandle(view);
2493 
2494     query = "SELECT * FROM `Table`";
2495     r = MsiDatabaseOpenViewA(hdb, query, &view);
2496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2497 
2498     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2500     count = MsiRecordGetFieldCount(rec);
2501     ok(count == 6, "Expected 6, got %d\n", count);
2502     ok(check_record(rec, 1, "A"), "Expected A\n");
2503     ok(check_record(rec, 2, "B"), "Expected B\n");
2504     ok(check_record(rec, 3, "C"), "Expected C\n");
2505     ok(check_record(rec, 4, "D"), "Expected D\n");
2506     ok(check_record(rec, 5, "E"), "Expected E\n");
2507     ok(check_record(rec, 6, "F"), "Expected F\n");
2508     MsiCloseHandle(rec);
2509 
2510     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2512     count = MsiRecordGetFieldCount(rec);
2513     ok(count == 6, "Expected 6, got %d\n", count);
2514     ok(check_record(rec, 1, "s72"), "Expected s72\n");
2515     ok(check_record(rec, 2, "s72"), "Expected s72\n");
2516     ok(check_record(rec, 3, "s72"), "Expected s72\n");
2517     ok(check_record(rec, 4, "s72"), "Expected s72\n");
2518     ok(check_record(rec, 5, "s72"), "Expected s72\n");
2519     ok(check_record(rec, 6, "s72"), "Expected s72\n");
2520     MsiCloseHandle(rec);
2521 
2522     MsiViewClose(view);
2523     MsiCloseHandle(view);
2524 
2525     query = "SELECT * FROM `Table`";
2526     r = MsiDatabaseOpenViewA(hdb, query, &view);
2527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2528 
2529     r = MsiViewExecute(view, 0);
2530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2531 
2532     r = MsiViewFetch(view, &rec);
2533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2534     ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2535     ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2536     ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2537     ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2538     ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2539     ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2540 
2541     MsiCloseHandle(rec);
2542 
2543     r = MsiViewFetch(view, &rec);
2544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2545     ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2546     ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2547     ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2548     ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2549     ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2550     ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2551 
2552     MsiCloseHandle(rec);
2553 
2554     r = MsiViewFetch(view, &rec);
2555     ok(r == ERROR_NO_MORE_ITEMS,
2556        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2557 
2558     MsiViewClose(view);
2559     MsiCloseHandle(view);
2560     MsiCloseHandle(hdb);
2561     DeleteFileA(msifile);
2562 }
2563 
2564 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2565                                      "s72\tV0\r\n"
2566                                      "Binary\tName\r\n"
2567                                      "filename1\tfilename1.ibd\r\n";
2568 
2569 static void test_binary_import(void)
2570 {
2571     MSIHANDLE hdb = 0, rec;
2572     char file[MAX_PATH];
2573     char buf[MAX_PATH];
2574     char path[MAX_PATH];
2575     DWORD size;
2576     LPCSTR query;
2577     UINT r;
2578 
2579     /* create files to import */
2580     write_file("bin_import.idt", bin_import_dat,
2581           (sizeof(bin_import_dat) - 1) * sizeof(char));
2582     CreateDirectoryA("bin_import", NULL);
2583     create_file_data("bin_import/filename1.ibd", "just some words", 15);
2584 
2585     /* import files into database */
2586     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2587     ok( r == ERROR_SUCCESS , "Failed to open database\n");
2588 
2589     GetCurrentDirectoryA(MAX_PATH, path);
2590     r = MsiDatabaseImportA(hdb, path, "bin_import.idt");
2591     ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2592 
2593     /* read file from the Binary table */
2594     query = "SELECT * FROM `Binary`";
2595     r = do_query(hdb, query, &rec);
2596     ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2597 
2598     size = MAX_PATH;
2599     r = MsiRecordGetStringA(rec, 1, file, &size);
2600     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2601     ok(!lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file);
2602 
2603     size = MAX_PATH;
2604     memset(buf, 0, MAX_PATH);
2605     r = MsiRecordReadStream(rec, 2, buf, &size);
2606     ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2607     ok(!lstrcmpA(buf, "just some words"), "Expected 'just some words', got %s\n", buf);
2608 
2609     r = MsiCloseHandle(rec);
2610     ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2611 
2612     r = MsiCloseHandle(hdb);
2613     ok(r == ERROR_SUCCESS , "Failed to close database\n");
2614 
2615     DeleteFileA("bin_import/filename1.ibd");
2616     RemoveDirectoryA("bin_import");
2617     DeleteFileA("bin_import.idt");
2618 }
2619 
2620 static void test_markers(void)
2621 {
2622     MSIHANDLE hdb, rec;
2623     LPCSTR query;
2624     UINT r;
2625 
2626     hdb = create_db();
2627     ok( hdb, "failed to create db\n");
2628 
2629     rec = MsiCreateRecord(3);
2630     MsiRecordSetStringA(rec, 1, "Table");
2631     MsiRecordSetStringA(rec, 2, "Apples");
2632     MsiRecordSetStringA(rec, 3, "Oranges");
2633 
2634     /* try a legit create */
2635     query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2636     r = run_query(hdb, 0, query);
2637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2638     MsiCloseHandle(rec);
2639 
2640     /* try table name as marker */
2641     rec = MsiCreateRecord(1);
2642     MsiRecordSetStringA(rec, 1, "Fable");
2643     query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2644     r = run_query(hdb, rec, query);
2645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2646 
2647     /* verify that we just created a table called '?', not 'Fable' */
2648     r = try_query(hdb, "SELECT * from `Fable`");
2649     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2650 
2651     r = try_query(hdb, "SELECT * from `?`");
2652     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2653 
2654     /* try table name as marker without backticks */
2655     MsiRecordSetStringA(rec, 1, "Mable");
2656     query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2657     r = run_query(hdb, rec, query);
2658     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2659 
2660     /* try one column name as marker */
2661     MsiRecordSetStringA(rec, 1, "One");
2662     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2663     r = run_query(hdb, rec, query);
2664     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2665     MsiCloseHandle(rec);
2666 
2667     /* try column names as markers */
2668     rec = MsiCreateRecord(2);
2669     MsiRecordSetStringA(rec, 1, "One");
2670     MsiRecordSetStringA(rec, 2, "Two");
2671     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2672     r = run_query(hdb, rec, query);
2673     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2674     MsiCloseHandle(rec);
2675 
2676     /* try names with backticks */
2677     rec = MsiCreateRecord(3);
2678     MsiRecordSetStringA(rec, 1, "One");
2679     MsiRecordSetStringA(rec, 2, "Two");
2680     MsiRecordSetStringA(rec, 3, "One");
2681     query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2682     r = run_query(hdb, rec, query);
2683     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2684 
2685     /* try names with backticks, minus definitions */
2686     query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2687     r = run_query(hdb, rec, query);
2688     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2689 
2690     /* try names without backticks */
2691     query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2692     r = run_query(hdb, rec, query);
2693     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2694     MsiCloseHandle(rec);
2695 
2696     /* try one long marker */
2697     rec = MsiCreateRecord(1);
2698     MsiRecordSetStringA(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2699     query = "CREATE TABLE `Mable` ( ? )";
2700     r = run_query(hdb, rec, query);
2701     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2702     MsiCloseHandle(rec);
2703 
2704     /* try all names as markers */
2705     rec = MsiCreateRecord(4);
2706     MsiRecordSetStringA(rec, 1, "Mable");
2707     MsiRecordSetStringA(rec, 2, "One");
2708     MsiRecordSetStringA(rec, 3, "Two");
2709     MsiRecordSetStringA(rec, 4, "One");
2710     query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2711     r = run_query(hdb, rec, query);
2712     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2713     MsiCloseHandle(rec);
2714 
2715     /* try a legit insert */
2716     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2717     r = run_query(hdb, 0, query);
2718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2719 
2720     r = try_query(hdb, "SELECT * from `Table`");
2721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2722 
2723     /* try values as markers */
2724     rec = MsiCreateRecord(2);
2725     MsiRecordSetInteger(rec, 1, 4);
2726     MsiRecordSetStringA(rec, 2, "hi");
2727     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2728     r = run_query(hdb, rec, query);
2729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2730     MsiCloseHandle(rec);
2731 
2732     /* try column names and values as markers */
2733     rec = MsiCreateRecord(4);
2734     MsiRecordSetStringA(rec, 1, "One");
2735     MsiRecordSetStringA(rec, 2, "Two");
2736     MsiRecordSetInteger(rec, 3, 5);
2737     MsiRecordSetStringA(rec, 4, "hi");
2738     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2739     r = run_query(hdb, rec, query);
2740     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2741     MsiCloseHandle(rec);
2742 
2743     /* try column names as markers */
2744     rec = MsiCreateRecord(2);
2745     MsiRecordSetStringA(rec, 1, "One");
2746     MsiRecordSetStringA(rec, 2, "Two");
2747     query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2748     r = run_query(hdb, rec, query);
2749     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2750     MsiCloseHandle(rec);
2751 
2752     /* try table name as a marker */
2753     rec = MsiCreateRecord(1);
2754     MsiRecordSetStringA(rec, 1, "Table");
2755     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2756     r = run_query(hdb, rec, query);
2757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2758     MsiCloseHandle(rec);
2759 
2760     /* try table name and values as markers */
2761     rec = MsiCreateRecord(3);
2762     MsiRecordSetStringA(rec, 1, "Table");
2763     MsiRecordSetInteger(rec, 2, 10);
2764     MsiRecordSetStringA(rec, 3, "haha");
2765     query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2766     r = run_query(hdb, rec, query);
2767     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2768     MsiCloseHandle(rec);
2769 
2770     /* try all markers */
2771     rec = MsiCreateRecord(5);
2772     MsiRecordSetStringA(rec, 1, "Table");
2773     MsiRecordSetStringA(rec, 1, "One");
2774     MsiRecordSetStringA(rec, 1, "Two");
2775     MsiRecordSetInteger(rec, 2, 10);
2776     MsiRecordSetStringA(rec, 3, "haha");
2777     query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2778     r = run_query(hdb, rec, query);
2779     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2780     MsiCloseHandle(rec);
2781 
2782     /* insert an integer as a string */
2783     rec = MsiCreateRecord(2);
2784     MsiRecordSetStringA(rec, 1, "11");
2785     MsiRecordSetStringA(rec, 2, "hi");
2786     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2787     r = run_query(hdb, rec, query);
2788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2789     MsiCloseHandle(rec);
2790 
2791     /* leave off the '' for the string */
2792     rec = MsiCreateRecord(2);
2793     MsiRecordSetInteger(rec, 1, 12);
2794     MsiRecordSetStringA(rec, 2, "hi");
2795     query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2796     r = run_query(hdb, rec, query);
2797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2798     MsiCloseHandle(rec);
2799 
2800     MsiCloseHandle(hdb);
2801     DeleteFileA(msifile);
2802 }
2803 
2804 #define MY_NVIEWS 4000    /* Largest installer I've seen uses < 2000 */
2805 static void test_handle_limit(void)
2806 {
2807     int i;
2808     MSIHANDLE hdb;
2809     MSIHANDLE hviews[MY_NVIEWS];
2810     UINT r;
2811 
2812     /* create an empty db */
2813     hdb = create_db();
2814     ok( hdb, "failed to create db\n");
2815 
2816     memset(hviews, 0, sizeof(hviews));
2817 
2818     for (i=0; i<MY_NVIEWS; i++) {
2819         static char szQueryBuf[256] = "SELECT * from `_Tables`";
2820         hviews[i] = 0xdeadbeeb;
2821         r = MsiDatabaseOpenViewA(hdb, szQueryBuf, &hviews[i]);
2822         if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb ||
2823             hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2824             break;
2825     }
2826 
2827     ok( i == MY_NVIEWS, "problem opening views\n");
2828 
2829     for (i=0; i<MY_NVIEWS; i++) {
2830         if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2831             MsiViewClose(hviews[i]);
2832             r = MsiCloseHandle(hviews[i]);
2833             if (r != ERROR_SUCCESS)
2834                 break;
2835         }
2836     }
2837 
2838     ok( i == MY_NVIEWS, "problem closing views\n");
2839 
2840     r = MsiCloseHandle(hdb);
2841     ok( r == ERROR_SUCCESS, "failed to close database\n");
2842 }
2843 
2844 static void generate_transform(void)
2845 {
2846     MSIHANDLE hdb1, hdb2, hrec;
2847     LPCSTR query;
2848     UINT r;
2849 
2850     /* start with two identical databases */
2851     CopyFileA(msifile2, msifile, FALSE);
2852 
2853     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb1 );
2854     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2855 
2856     r = MsiDatabaseCommit( hdb1 );
2857     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2858 
2859     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_READONLY, &hdb2 );
2860     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2861 
2862     /* the transform between two identical database should be empty */
2863     r = MsiDatabaseGenerateTransformA(hdb1, hdb2, NULL, 0, 0);
2864     todo_wine {
2865     ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2866     }
2867 
2868     query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2869     r = run_query(hdb1, 0, query);
2870     ok(r == ERROR_SUCCESS, "failed to add table\n");
2871 
2872     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2873     r = run_query(hdb1, 0, query);
2874     ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2875 
2876     query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2877     r = run_query(hdb1, 0, query);
2878     ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2879 
2880     query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2881     r = run_query(hdb1, 0, query);
2882     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2883 
2884     query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2885     r = run_query(hdb1, 0, query);
2886     ok(r == ERROR_SUCCESS, "failed to delete row\n");
2887 
2888     hrec = MsiCreateRecord(2);
2889     r = MsiRecordSetInteger(hrec, 1, 1);
2890     ok(r == ERROR_SUCCESS, "failed to set integer\n");
2891 
2892     write_file("testdata.bin", "naengmyon", 9);
2893     r = MsiRecordSetStreamA(hrec, 2, "testdata.bin");
2894     ok(r == ERROR_SUCCESS, "failed to set stream\n");
2895 
2896     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2897     r = run_query(hdb1, hrec, query);
2898     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2899 
2900     MsiCloseHandle(hrec);
2901 
2902     query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2903     r = run_query(hdb1, 0, query);
2904     ok(r == ERROR_SUCCESS, "failed to add column\n");
2905 
2906     query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2907     r = run_query(hdb1, 0, query);
2908     ok(r == ERROR_SUCCESS, "failed to add column\n");
2909 
2910     query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2911     r = run_query(hdb1, 0, query);
2912     ok(r == ERROR_SUCCESS, "failed to modify row\n");
2913 
2914     query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2915             "`Value` CHAR(0) PRIMARY KEY `Property`)";
2916     r = run_query(hdb1, 0, query);
2917     ok(r == ERROR_SUCCESS, "failed to add property table\n");
2918 
2919     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2920     r = run_query(hdb1, 0, query);
2921     ok(r == ERROR_SUCCESS, "failed to add property\n");
2922 
2923     /* database needs to be committed */
2924     MsiDatabaseCommit(hdb1);
2925 
2926     r = MsiDatabaseGenerateTransformA(hdb1, hdb2, mstfile, 0, 0);
2927     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2928 
2929     MsiCloseHandle( hdb1 );
2930     MsiCloseHandle( hdb2 );
2931 
2932     DeleteFileA("testdata.bin");
2933 }
2934 
2935 /* data for generating a transform */
2936 
2937 /* tables transform names - encoded as they would be in an msi database file */
2938 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2939 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2940 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2941 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2942 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2943 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2944 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2945 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2946 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2947 
2948 /* data in each table */
2949 static const WCHAR data1[] = { /* AAR */
2950     0x0201, 0x0008, 0x8001,  /* 0x0201 = add row (1), two shorts */
2951     0x0201, 0x0009, 0x8002,
2952 };
2953 static const WCHAR data2[] = { /* _Columns */
2954     0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2955     0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2956     0x0401, 0x0005, 0x0000, 0x0006, 0xbdff,  /* 0x0401 = add row (1), 4 shorts */
2957     0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2958     0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2959     0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2960 };
2961 static const WCHAR data3[] = { /* _Tables */
2962     0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2963     0x0101, 0x000a,
2964 };
2965 static const char data4[] = /* _StringData */
2966     "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval";  /* all the strings squashed together */
2967 static const WCHAR data5[] = { /* _StringPool */
2968 /*  len, refs */
2969     0,   0,    /* string 0 ''    */
2970     3,   2,    /* string 1 'MOO' */
2971     3,   1,    /* string 2 'COW' */
2972     3,   1,    /* string 3 'PIG' */
2973     1,   1,    /* string 4 'c'   */
2974     3,   3,    /* string 5 'AAR' */
2975     3,   1,    /* string 6 'CAR' */
2976     3,   1,    /* string 7 'BAR' */
2977     2,   1,    /* string 8 'vw'  */
2978     3,   1,    /* string 9 'bmw' */
2979     8,   4,    /* string 10 'Property' */
2980     5,   1,    /* string 11 'Value' */
2981     4,   1,    /* string 12 'prop' */
2982     3,   1,    /* string 13 'val' */
2983 };
2984 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2985 static const WCHAR data6[] = { /* MOO */
2986     0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2987     0x0000, 0x8003,         /* delete row */
2988 };
2989 
2990 static const WCHAR data7[] = { /* BINARY */
2991     0x0201, 0x8001, 0x0001,
2992 };
2993 
2994 static const char data8[] =  /* stream data for the BINARY table */
2995     "naengmyon";
2996 
2997 static const WCHAR data9[] = { /* Property */
2998     0x0201, 0x000c, 0x000d,
2999 };
3000 
3001 static const struct {
3002     LPCWSTR name;
3003     const void *data;
3004     DWORD size;
3005 } table_transform_data[] =
3006 {
3007     { name1, data1, sizeof data1 },
3008     { name2, data2, sizeof data2 },
3009     { name3, data3, sizeof data3 },
3010     { name4, data4, sizeof data4 - 1 },
3011     { name5, data5, sizeof data5 },
3012     { name6, data6, sizeof data6 },
3013     { name7, data7, sizeof data7 },
3014     { name8, data8, sizeof data8 - 1 },
3015     { name9, data9, sizeof data9 },
3016 };
3017 
3018 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
3019 
3020 static void generate_transform_manual(void)
3021 {
3022     IStorage *stg = NULL;
3023     IStream *stm;
3024     WCHAR name[0x20];
3025     HRESULT r;
3026     DWORD i, count;
3027     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
3028 
3029     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
3030 
3031     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
3032 
3033     r = StgCreateDocfile(name, mode, 0, &stg);
3034     ok(r == S_OK, "failed to create storage\n");
3035     if (!stg)
3036         return;
3037 
3038     r = IStorage_SetClass( stg, &CLSID_MsiTransform );
3039     ok(r == S_OK, "failed to set storage type\n");
3040 
3041     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
3042     {
3043         r = IStorage_CreateStream( stg, table_transform_data[i].name,
3044                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
3045         if (FAILED(r))
3046         {
3047             ok(0, "failed to create stream %08x\n", r);
3048             continue;
3049         }
3050 
3051         r = IStream_Write( stm, table_transform_data[i].data,
3052                           table_transform_data[i].size, &count );
3053         if (FAILED(r) || count != table_transform_data[i].size)
3054             ok(0, "failed to write stream\n");
3055         IStream_Release(stm);
3056     }
3057 
3058     IStorage_Release(stg);
3059 }
3060 
3061 static UINT set_summary_info(MSIHANDLE hdb)
3062 {
3063     UINT res;
3064     MSIHANDLE suminfo;
3065 
3066     /* build summary info */
3067     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
3068     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
3069 
3070     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
3071                         "Installation Database");
3072     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3073 
3074     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
3075                         "Installation Database");
3076     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3077 
3078     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
3079                         "Wine Hackers");
3080     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3081 
3082     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
3083                     ";1033,2057");
3084     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3085 
3086     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
3087                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
3088     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3089 
3090     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
3091     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3092 
3093     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
3094     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3095 
3096     res = MsiSummaryInfoPersist(suminfo);
3097     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
3098 
3099     res = MsiCloseHandle( suminfo);
3100     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
3101 
3102     return res;
3103 }
3104 
3105 static MSIHANDLE create_package_db(const WCHAR *filename)
3106 {
3107     MSIHANDLE hdb = 0;
3108     UINT res;
3109 
3110     DeleteFileW(msifileW);
3111 
3112     /* create an empty database */
3113     res = MsiOpenDatabaseW(filename, MSIDBOPEN_CREATE, &hdb );
3114     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
3115     if( res != ERROR_SUCCESS )
3116         return hdb;
3117 
3118     res = MsiDatabaseCommit( hdb );
3119     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
3120 
3121     res = set_summary_info(hdb);
3122     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3123 
3124     res = create_directory_table(hdb);
3125     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
3126 
3127     return hdb;
3128 }
3129 
3130 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
3131 {
3132     UINT res;
3133     CHAR szPackage[12];
3134     MSIHANDLE hPackage;
3135 
3136     sprintf(szPackage, "#%u", hdb);
3137     res = MsiOpenPackageA(szPackage, &hPackage);
3138     if (res != ERROR_SUCCESS)
3139         return res;
3140 
3141     res = MsiCloseHandle(hdb);
3142     if (res != ERROR_SUCCESS)
3143     {
3144         MsiCloseHandle(hPackage);
3145         return res;
3146     }
3147 
3148     *handle = hPackage;
3149     return ERROR_SUCCESS;
3150 }
3151 
3152 static void test_try_transform(void)
3153 {
3154     MSIHANDLE hdb, hview, hrec, hpkg = 0;
3155     LPCSTR query;
3156     UINT r;
3157     DWORD sz;
3158     char buffer[MAX_PATH];
3159 
3160     DeleteFileA(msifile);
3161     DeleteFileA(mstfile);
3162 
3163     /* create the database */
3164     hdb = create_package_db(msifileW);
3165     ok(hdb, "Failed to create package db\n");
3166 
3167     query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
3168     r = run_query(hdb, 0, query);
3169     ok(r == ERROR_SUCCESS, "failed to add table\n");
3170 
3171     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
3172     r = run_query(hdb, 0, query);
3173     ok(r == ERROR_SUCCESS, "failed to add row\n");
3174 
3175     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
3176     r = run_query(hdb, 0, query);
3177     ok(r == ERROR_SUCCESS, "failed to add row\n");
3178 
3179     query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
3180     r = run_query(hdb, 0, query);
3181     ok(r == ERROR_SUCCESS, "failed to add row\n");
3182 
3183     query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
3184     r = run_query(hdb, 0, query);
3185     ok(r == ERROR_SUCCESS, "failed to add table\n");
3186 
3187     hrec = MsiCreateRecord(2);
3188     r = MsiRecordSetInteger(hrec, 1, 2);
3189     ok(r == ERROR_SUCCESS, "failed to set integer\n");
3190 
3191     write_file("testdata.bin", "lamyon", 6);
3192     r = MsiRecordSetStreamA(hrec, 2, "testdata.bin");
3193     ok(r == ERROR_SUCCESS, "failed to set stream\n");
3194 
3195     query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3196     r = run_query(hdb, hrec, query);
3197     ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3198 
3199     MsiCloseHandle(hrec);
3200 
3201     r = MsiDatabaseCommit( hdb );
3202     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3203 
3204     MsiCloseHandle( hdb );
3205     DeleteFileA("testdata.bin");
3206 
3207     /*
3208      * Both these generate an equivalent transform,
3209      *  but the first doesn't work in Wine yet
3210      *  because MsiDatabaseGenerateTransform is unimplemented.
3211      */
3212     if (0)
3213         generate_transform();
3214     else
3215         generate_transform_manual();
3216 
3217     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb );
3218     ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3219 
3220     r = MsiDatabaseApplyTransformA( hdb, mstfile, 0 );
3221     ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3222 
3223     r = MsiDatabaseCommit( hdb );
3224     ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3225 
3226     /* check new values */
3227     hrec = 0;
3228     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3229     r = do_query(hdb, query, &hrec);
3230     ok(r == ERROR_SUCCESS, "select query failed\n");
3231     MsiCloseHandle(hrec);
3232 
3233     query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3234     hrec = 0;
3235     r = do_query(hdb, query, &hrec);
3236     ok(r == ERROR_SUCCESS, "select query failed\n");
3237     MsiCloseHandle(hrec);
3238 
3239     /* check updated values */
3240     hrec = 0;
3241     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3242     r = do_query(hdb, query, &hrec);
3243     ok(r == ERROR_SUCCESS, "select query failed\n");
3244     MsiCloseHandle(hrec);
3245 
3246     /* check unchanged value */
3247     hrec = 0;
3248     query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3249     r = do_query(hdb, query, &hrec);
3250     ok(r == ERROR_SUCCESS, "select query failed\n");
3251     MsiCloseHandle(hrec);
3252 
3253     /* check deleted value */
3254     hrec = 0;
3255     query = "select * from `MOO` where `NOO` = 3";
3256     r = do_query(hdb, query, &hrec);
3257     ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3258     if (hrec) MsiCloseHandle(hrec);
3259 
3260     /* check added stream */
3261     hrec = 0;
3262     query = "select `BLOB` from `BINARY` where `ID` = 1";
3263     r = do_query(hdb, query, &hrec);
3264     ok(r == ERROR_SUCCESS, "select query failed\n");
3265 
3266     /* check the contents of the stream */
3267     sz = sizeof buffer;
3268     r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3269     ok(r == ERROR_SUCCESS, "read stream failed\n");
3270     ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3271     ok(sz == 9, "stream data was wrong size\n");
3272     if (hrec) MsiCloseHandle(hrec);
3273 
3274     /* check the validity of the table with a deleted row */
3275     hrec = 0;
3276     query = "select * from `MOO`";
3277     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3278     ok(r == ERROR_SUCCESS, "open view failed\n");
3279 
3280     r = MsiViewExecute(hview, 0);
3281     ok(r == ERROR_SUCCESS, "view execute failed\n");
3282 
3283     r = MsiViewFetch(hview, &hrec);
3284     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3285 
3286     r = MsiRecordGetInteger(hrec, 1);
3287     ok(r == 1, "Expected 1, got %d\n", r);
3288 
3289     sz = sizeof buffer;
3290     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
3291     ok(r == ERROR_SUCCESS, "record get string failed\n");
3292     ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3293 
3294     r = MsiRecordGetInteger(hrec, 3);
3295     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3296 
3297     r = MsiRecordGetInteger(hrec, 4);
3298     ok(r == 5, "Expected 5, got %d\n", r);
3299 
3300     MsiCloseHandle(hrec);
3301 
3302     r = MsiViewFetch(hview, &hrec);
3303     ok(r == ERROR_SUCCESS, "view fetch failed\n");
3304 
3305     r = MsiRecordGetInteger(hrec, 1);
3306     ok(r == 2, "Expected 2, got %d\n", r);
3307 
3308     sz = sizeof buffer;
3309     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
3310     ok(r == ERROR_SUCCESS, "record get string failed\n");
3311     ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3312 
3313     r = MsiRecordGetInteger(hrec, 3);
3314     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3315 
3316     r = MsiRecordGetInteger(hrec, 4);
3317     ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3318 
3319     MsiCloseHandle(hrec);
3320 
3321     r = MsiViewFetch(hview, &hrec);
3322     ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3323 
3324     MsiCloseHandle(hrec);
3325     MsiViewClose(hview);
3326     MsiCloseHandle(hview);
3327 
3328     /* check that the property was added */
3329     r = package_from_db(hdb, &hpkg);
3330     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3331     {
3332         skip("Not enough rights to perform tests\n");
3333         goto error;
3334     }
3335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3336 
3337     sz = MAX_PATH;
3338     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
3339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3340     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
3341 
3342     MsiCloseHandle(hpkg);
3343 
3344 error:
3345     MsiCloseHandle(hdb);
3346     DeleteFileA(msifile);
3347     DeleteFileA(mstfile);
3348 }
3349 
3350 struct join_res
3351 {
3352     const CHAR one[MAX_PATH];
3353     const CHAR two[MAX_PATH];
3354 };
3355 
3356 struct join_res_4col
3357 {
3358     const CHAR one[MAX_PATH];
3359     const CHAR two[MAX_PATH];
3360     const CHAR three[MAX_PATH];
3361     const CHAR four[MAX_PATH];
3362 };
3363 
3364 struct join_res_uint
3365 {
3366     UINT one;
3367     UINT two;
3368     UINT three;
3369     UINT four;
3370     UINT five;
3371     UINT six;
3372 };
3373 
3374 static const struct join_res join_res_first[] =
3375 {
3376     { "alveolar", "procerus" },
3377     { "septum", "procerus" },
3378     { "septum", "nasalis" },
3379     { "ramus", "nasalis" },
3380     { "malar", "mentalis" },
3381 };
3382 
3383 static const struct join_res join_res_second[] =
3384 {
3385     { "nasal", "septum" },
3386     { "mandible", "ramus" },
3387 };
3388 
3389 static const struct join_res join_res_third[] =
3390 {
3391     { "msvcp.dll", "abcdefgh" },
3392     { "msvcr.dll", "ijklmnop" },
3393 };
3394 
3395 static const struct join_res join_res_fourth[] =
3396 {
3397     { "msvcp.dll.01234", "single.dll.31415" },
3398 };
3399 
3400 static const struct join_res join_res_fifth[] =
3401 {
3402     { "malar", "procerus" },
3403 };
3404 
3405 static const struct join_res join_res_sixth[] =
3406 {
3407     { "malar", "procerus" },
3408     { "malar", "procerus" },
3409     { "malar", "nasalis" },
3410     { "malar", "nasalis" },
3411     { "malar", "nasalis" },
3412     { "malar", "mentalis" },
3413 };
3414 
3415 static const struct join_res join_res_seventh[] =
3416 {
3417     { "malar", "nasalis" },
3418     { "malar", "nasalis" },
3419     { "malar", "nasalis" },
3420 };
3421 
3422 static const struct join_res_4col join_res_eighth[] =
3423 {
3424     { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3425     { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3426     { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3427     { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3428     { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3429     { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3430 };
3431 
3432 static const struct join_res_uint join_res_ninth[] =
3433 {
3434     { 1, 2, 3, 4, 7, 8 },
3435     { 1, 2, 5, 6, 7, 8 },
3436     { 1, 2, 3, 4, 9, 10 },
3437     { 1, 2, 5, 6, 9, 10 },
3438     { 1, 2, 3, 4, 11, 12 },
3439     { 1, 2, 5, 6, 11, 12 },
3440 };
3441 
3442 static void test_join(void)
3443 {
3444     MSIHANDLE hdb, hview, hrec;
3445     LPCSTR query;
3446     CHAR buf[MAX_PATH];
3447     UINT r, count;
3448     DWORD size, i;
3449     BOOL data_correct;
3450 
3451     hdb = create_db();
3452     ok( hdb, "failed to create db\n");
3453 
3454     r = create_component_table( hdb );
3455     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3456 
3457     r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3458     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3459 
3460     r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3461     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3462 
3463     r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3464     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3465 
3466     r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3467     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3468 
3469     r = create_feature_components_table( hdb );
3470     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3471 
3472     r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3473     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3474 
3475     r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3476     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3477 
3478     r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3479     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3480 
3481     r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3482     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3483 
3484     r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3485     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3486 
3487     r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3488     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3489 
3490     r = create_std_dlls_table( hdb );
3491     ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3492 
3493     r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3494     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3495 
3496     r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3497     ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3498 
3499     r = create_binary_table( hdb );
3500     ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3501 
3502     r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3503     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3504 
3505     r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3506     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3507 
3508     r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3509     ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3510 
3511     query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3512     r = run_query( hdb, 0, query);
3513     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3514 
3515     query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3516     r = run_query( hdb, 0, query);
3517     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3518 
3519     query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3520     r = run_query( hdb, 0, query);
3521     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3522 
3523     query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3524     r = run_query( hdb, 0, query);
3525     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3526 
3527     query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3528     r = run_query( hdb, 0, query);
3529     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3530 
3531     query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3532     r = run_query( hdb, 0, query);
3533     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3534 
3535     query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3536     r = run_query( hdb, 0, query);
3537     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3538 
3539     query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3540     r = run_query( hdb, 0, query);
3541     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3542 
3543     query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3544     r = run_query( hdb, 0, query);
3545     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3546 
3547     query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3548     r = run_query( hdb, 0, query);
3549     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3550 
3551     query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3552     r = run_query( hdb, 0, query);
3553     ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3554 
3555     query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3556     r = run_query( hdb, 0, query);
3557     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3558 
3559     query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3560     r = run_query( hdb, 0, query);
3561     ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3562 
3563     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3564             "FROM `Component`, `FeatureComponents` "
3565             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3566             "ORDER BY `Feature_`";
3567     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3568     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3569 
3570     r = MsiViewExecute(hview, 0);
3571     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3572 
3573     i = 0;
3574     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3575     {
3576         count = MsiRecordGetFieldCount( hrec );
3577         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3578 
3579         size = MAX_PATH;
3580         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3581         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3582         ok( !lstrcmpA( buf, join_res_first[i].one ),
3583             "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3584 
3585         size = MAX_PATH;
3586         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3587         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3588         ok( !lstrcmpA( buf, join_res_first[i].two ),
3589             "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3590 
3591         i++;
3592         MsiCloseHandle(hrec);
3593     }
3594 
3595     ok( i == 5, "Expected 5 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     /* try a join without a WHERE condition */
3602     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3603             "FROM `Component`, `FeatureComponents` ";
3604     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3605     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3606 
3607     r = MsiViewExecute(hview, 0);
3608     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3609 
3610     i = 0;
3611     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3612     {
3613         i++;
3614         MsiCloseHandle(hrec);
3615     }
3616     ok( i == 24, "Expected 24 rows, got %d\n", i );
3617 
3618     MsiViewClose(hview);
3619     MsiCloseHandle(hview);
3620 
3621     query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3622             "WHERE FeatureComponents.Component_=Component.Component "
3623             "AND (Feature_='nasalis') ORDER BY Feature_";
3624     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3625     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3626 
3627     r = MsiViewExecute(hview, 0);
3628     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3629 
3630     i = 0;
3631     data_correct = TRUE;
3632     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3633     {
3634         count = MsiRecordGetFieldCount( hrec );
3635         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3636 
3637         size = MAX_PATH;
3638         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3639         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3640         if( lstrcmpA( buf, join_res_second[i].one ))
3641             data_correct = FALSE;
3642 
3643         size = MAX_PATH;
3644         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3645         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3646         if( lstrcmpA( buf, join_res_second[i].two ))
3647             data_correct = FALSE;
3648 
3649         i++;
3650         MsiCloseHandle(hrec);
3651     }
3652 
3653     ok( data_correct, "data returned in the wrong order\n");
3654 
3655     ok( i == 2, "Expected 2 rows, got %d\n", i );
3656     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3657 
3658     MsiViewClose(hview);
3659     MsiCloseHandle(hview);
3660 
3661     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3662             "FROM `StdDlls`, `Binary` "
3663             "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3664             "ORDER BY `File`";
3665     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3666     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3667 
3668     r = MsiViewExecute(hview, 0);
3669     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3670 
3671     i = 0;
3672     data_correct = TRUE;
3673     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3674     {
3675         count = MsiRecordGetFieldCount( hrec );
3676         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3677 
3678         size = MAX_PATH;
3679         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3680         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3681         if( lstrcmpA( buf, join_res_third[i].one ) )
3682             data_correct = FALSE;
3683 
3684         size = MAX_PATH;
3685         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3686         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3687         if( lstrcmpA( buf, join_res_third[i].two ) )
3688             data_correct = FALSE;
3689 
3690         i++;
3691         MsiCloseHandle(hrec);
3692     }
3693     ok( data_correct, "data returned in the wrong order\n");
3694 
3695     ok( i == 2, "Expected 2 rows, got %d\n", i );
3696 
3697     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3698 
3699     MsiViewClose(hview);
3700     MsiCloseHandle(hview);
3701 
3702     query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3703             "FROM `StdDlls`, `Binary` "
3704             "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3705             "ORDER BY `Name`";
3706     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3707     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3708 
3709     r = MsiViewExecute(hview, 0);
3710     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3711 
3712     i = 0;
3713     data_correct = TRUE;
3714     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3715     {
3716         count = MsiRecordGetFieldCount( hrec );
3717         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3718 
3719         size = MAX_PATH;
3720         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3721         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3722         if( lstrcmpA( buf, join_res_fourth[i].one ))
3723             data_correct = FALSE;
3724 
3725         size = MAX_PATH;
3726         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3727         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3728         if( lstrcmpA( buf, join_res_fourth[i].two ))
3729             data_correct = FALSE;
3730 
3731         i++;
3732         MsiCloseHandle(hrec);
3733     }
3734     ok( data_correct, "data returned in the wrong order\n");
3735 
3736     ok( i == 1, "Expected 1 rows, got %d\n", i );
3737     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3738 
3739     MsiViewClose(hview);
3740     MsiCloseHandle(hview);
3741 
3742     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3743             "FROM `Component`, `FeatureComponents` "
3744             "WHERE `Component`.`Component` = 'zygomatic' "
3745             "AND `FeatureComponents`.`Component_` = 'maxilla' "
3746             "ORDER BY `Feature_`";
3747     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3748     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3749 
3750     r = MsiViewExecute(hview, 0);
3751     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3752 
3753     i = 0;
3754     data_correct = TRUE;
3755     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3756     {
3757         count = MsiRecordGetFieldCount( hrec );
3758         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3759 
3760         size = MAX_PATH;
3761         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3762         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3763         if( lstrcmpA( buf, join_res_fifth[i].one ))
3764             data_correct = FALSE;
3765 
3766         size = MAX_PATH;
3767         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3768         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3769         if( lstrcmpA( buf, join_res_fifth[i].two ))
3770             data_correct = FALSE;
3771 
3772         i++;
3773         MsiCloseHandle(hrec);
3774     }
3775     ok( data_correct, "data returned in the wrong order\n");
3776 
3777     ok( i == 1, "Expected 1 rows, got %d\n", i );
3778     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3779 
3780     MsiViewClose(hview);
3781     MsiCloseHandle(hview);
3782 
3783     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3784             "FROM `Component`, `FeatureComponents` "
3785             "WHERE `Component` = 'zygomatic' "
3786             "ORDER BY `Feature_`";
3787     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3788     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3789 
3790     r = MsiViewExecute(hview, 0);
3791     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3792 
3793     i = 0;
3794     data_correct = TRUE;
3795     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3796     {
3797         count = MsiRecordGetFieldCount( hrec );
3798         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3799 
3800         size = MAX_PATH;
3801         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3802         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3803         if( lstrcmpA( buf, join_res_sixth[i].one ))
3804             data_correct = FALSE;
3805 
3806         size = MAX_PATH;
3807         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3808         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3809         if( lstrcmpA( buf, join_res_sixth[i].two ))
3810             data_correct = FALSE;
3811 
3812         i++;
3813         MsiCloseHandle(hrec);
3814     }
3815     ok( data_correct, "data returned in the wrong order\n");
3816 
3817     ok( i == 6, "Expected 6 rows, got %d\n", i );
3818     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3819 
3820     MsiViewClose(hview);
3821     MsiCloseHandle(hview);
3822 
3823     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3824             "FROM `Component`, `FeatureComponents` "
3825             "WHERE `Component` = 'zygomatic' "
3826             "AND `Feature_` = 'nasalis' "
3827             "ORDER BY `Feature_`";
3828     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3829     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3830 
3831     r = MsiViewExecute(hview, 0);
3832     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3833 
3834     i = 0;
3835     data_correct = TRUE;
3836     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3837     {
3838         count = MsiRecordGetFieldCount( hrec );
3839         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3840 
3841         size = MAX_PATH;
3842         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3843         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3844         if( lstrcmpA( buf, join_res_seventh[i].one ))
3845             data_correct = FALSE;
3846 
3847         size = MAX_PATH;
3848         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3849         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3850         if( lstrcmpA( buf, join_res_seventh[i].two ))
3851             data_correct = FALSE;
3852 
3853         i++;
3854         MsiCloseHandle(hrec);
3855     }
3856 
3857     ok( data_correct, "data returned in the wrong order\n");
3858     ok( i == 3, "Expected 3 rows, got %d\n", i );
3859     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3860 
3861     MsiViewClose(hview);
3862     MsiCloseHandle(hview);
3863 
3864     query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3865             "FROM `StdDlls`, `Binary` ";
3866     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3867     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3868 
3869     r = MsiViewExecute(hview, 0);
3870     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3871 
3872     i = 0;
3873     data_correct = TRUE;
3874     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3875     {
3876         count = MsiRecordGetFieldCount( hrec );
3877         ok( count == 2, "Expected 2 record fields, got %d\n", count );
3878 
3879         size = MAX_PATH;
3880         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3881         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3882         if( lstrcmpA( buf, join_res_eighth[i].one ))
3883             data_correct = FALSE;
3884 
3885         size = MAX_PATH;
3886         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3887         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3888         if( lstrcmpA( buf, join_res_eighth[i].four ))
3889             data_correct = FALSE;
3890 
3891         i++;
3892         MsiCloseHandle(hrec);
3893     }
3894 
3895     ok( data_correct, "data returned in the wrong order\n");
3896     ok( i == 6, "Expected 6 rows, got %d\n", i );
3897     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3898 
3899     MsiViewClose(hview);
3900     MsiCloseHandle(hview);
3901 
3902     query = "SELECT * FROM `StdDlls`, `Binary` ";
3903     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3904     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3905 
3906     r = MsiViewExecute(hview, 0);
3907     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3908 
3909     i = 0;
3910     data_correct = TRUE;
3911     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3912     {
3913         count = MsiRecordGetFieldCount( hrec );
3914         ok( count == 4, "Expected 4 record fields, got %d\n", count );
3915 
3916         size = MAX_PATH;
3917         r = MsiRecordGetStringA( hrec, 1, buf, &size );
3918         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3919         if( lstrcmpA( buf, join_res_eighth[i].one ))
3920             data_correct = FALSE;
3921 
3922         size = MAX_PATH;
3923         r = MsiRecordGetStringA( hrec, 2, buf, &size );
3924         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3925         if( lstrcmpA( buf, join_res_eighth[i].two ))
3926             data_correct = FALSE;
3927 
3928         size = MAX_PATH;
3929         r = MsiRecordGetStringA( hrec, 3, buf, &size );
3930         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3931         if( lstrcmpA( buf, join_res_eighth[i].three ))
3932             data_correct = FALSE;
3933 
3934         size = MAX_PATH;
3935         r = MsiRecordGetStringA( hrec, 4, buf, &size );
3936         ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3937         if( lstrcmpA( buf, join_res_eighth[i].four ))
3938             data_correct = FALSE;
3939 
3940         i++;
3941         MsiCloseHandle(hrec);
3942     }
3943     ok( data_correct, "data returned in the wrong order\n");
3944 
3945     ok( i == 6, "Expected 6 rows, got %d\n", i );
3946     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3947 
3948     MsiViewClose(hview);
3949     MsiCloseHandle(hview);
3950 
3951     query = "SELECT * FROM `One`, `Two`, `Three` ";
3952     r = MsiDatabaseOpenViewA(hdb, query, &hview);
3953     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3954 
3955     r = MsiViewExecute(hview, 0);
3956     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3957 
3958     i = 0;
3959     data_correct = TRUE;
3960     while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3961     {
3962         count = MsiRecordGetFieldCount( hrec );
3963         ok( count == 6, "Expected 6 record fields, got %d\n", count );
3964 
3965         r = MsiRecordGetInteger( hrec, 1 );
3966         if( r != join_res_ninth[i].one )
3967             data_correct = FALSE;
3968 
3969         r = MsiRecordGetInteger( hrec, 2 );
3970         if( r != join_res_ninth[i].two )
3971             data_correct = FALSE;
3972 
3973         r = MsiRecordGetInteger( hrec, 3 );
3974         if( r != join_res_ninth[i].three )
3975             data_correct = FALSE;
3976 
3977         r = MsiRecordGetInteger( hrec, 4 );
3978         if( r != join_res_ninth[i].four )
3979             data_correct = FALSE;
3980 
3981         r = MsiRecordGetInteger( hrec, 5 );
3982         if( r != join_res_ninth[i].five )
3983             data_correct = FALSE;
3984 
3985         r = MsiRecordGetInteger( hrec, 6);
3986         if( r != join_res_ninth[i].six )
3987             data_correct = FALSE;
3988 
3989         i++;
3990         MsiCloseHandle(hrec);
3991     }
3992     ok( data_correct, "data returned in the wrong order\n");
3993 
3994     ok( i == 6, "Expected 6 rows, got %d\n", i );
3995     ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3996 
3997     MsiViewClose(hview);
3998     MsiCloseHandle(hview);
3999 
4000     query = "SELECT * FROM `Four`, `Five`";
4001     r = MsiDatabaseOpenViewA(hdb, query, &hview);
4002     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
4003 
4004     r = MsiViewExecute(hview, 0);
4005     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
4006 
4007     r = MsiViewFetch(hview, &hrec);
4008     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4009 
4010     MsiViewClose(hview);
4011     MsiCloseHandle(hview);
4012 
4013     query = "SELECT * FROM `Nonexistent`, `One`";
4014     r = MsiDatabaseOpenViewA(hdb, query, &hview);
4015     ok( r == ERROR_BAD_QUERY_SYNTAX,
4016         "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
4017 
4018     /* try updating a row in a join table */
4019     query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
4020             "FROM `Component`, `FeatureComponents` "
4021             "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
4022             "ORDER BY `Feature_`";
4023     r = MsiDatabaseOpenViewA(hdb, query, &hview);
4024     ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
4025 
4026     r = MsiViewExecute(hview, 0);
4027     ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
4028 
4029     r = MsiViewFetch(hview, &hrec);
4030     ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
4031 
4032     r = MsiRecordSetStringA( hrec, 1, "epicranius" );
4033     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
4034 
4035     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
4036     ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
4037 
4038     /* try another valid operation for joins */
4039     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
4040     todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
4041 
4042     /* try an invalid operation for joins */
4043     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
4044     ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
4045 
4046     r = MsiRecordSetStringA( hrec, 2, "epicranius" );
4047     ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
4048 
4049     /* primary key cannot be updated */
4050     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
4051     ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
4052 
4053     MsiCloseHandle(hrec);
4054     MsiViewClose(hview);
4055     MsiCloseHandle(hview);
4056 
4057     r = MsiDatabaseOpenViewA(hdb, query, &hview);
4058     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4059 
4060     r = MsiViewExecute(hview, 0);
4061     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4062 
4063     r = MsiViewFetch(hview, &hrec);
4064     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4065 
4066     size = MAX_PATH;
4067     r = MsiRecordGetStringA( hrec, 1, buf, &size );
4068     ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
4069     ok( !lstrcmpA( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
4070 
4071     MsiCloseHandle(hrec);
4072     MsiViewClose(hview);
4073     MsiCloseHandle(hview);
4074 
4075     MsiCloseHandle(hdb);
4076     DeleteFileA(msifile);
4077 }
4078 
4079 static void test_temporary_table(void)
4080 {
4081     MSICONDITION cond;
4082     MSIHANDLE hdb = 0, view = 0, rec;
4083     const char *query;
4084     UINT r;
4085     char buf[0x10];
4086     DWORD sz;
4087 
4088     cond = MsiDatabaseIsTablePersistentA(0, NULL);
4089     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
4090 
4091     hdb = create_db();
4092     ok( hdb, "failed to create db\n");
4093 
4094     cond = MsiDatabaseIsTablePersistentA(hdb, NULL);
4095     ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
4096 
4097     cond = MsiDatabaseIsTablePersistentA(hdb, "_Tables");
4098     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4099 
4100     cond = MsiDatabaseIsTablePersistentA(hdb, "_Columns");
4101     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4102 
4103     cond = MsiDatabaseIsTablePersistentA(hdb, "_Storages");
4104     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4105 
4106     cond = MsiDatabaseIsTablePersistentA(hdb, "_Streams");
4107     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4108 
4109     query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
4110     r = run_query(hdb, 0, query);
4111     ok(r == ERROR_SUCCESS, "failed to add table\n");
4112 
4113     cond = MsiDatabaseIsTablePersistentA(hdb, "P");
4114     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4115 
4116     query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
4117     r = run_query(hdb, 0, query);
4118     ok(r == ERROR_SUCCESS, "failed to add table\n");
4119 
4120     cond = MsiDatabaseIsTablePersistentA(hdb, "P2");
4121     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4122 
4123     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4124     r = run_query(hdb, 0, query);
4125     ok(r == ERROR_SUCCESS, "failed to add table\n");
4126 
4127     cond = MsiDatabaseIsTablePersistentA(hdb, "T");
4128     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4129 
4130     query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4131     r = run_query(hdb, 0, query);
4132     ok(r == ERROR_SUCCESS, "failed to add table\n");
4133 
4134     query = "SELECT * FROM `T2`";
4135     r = MsiDatabaseOpenViewA(hdb, query, &view);
4136     ok(r == ERROR_BAD_QUERY_SYNTAX,
4137        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4138 
4139     cond = MsiDatabaseIsTablePersistentA(hdb, "T2");
4140     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4141 
4142     query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
4143     r = run_query(hdb, 0, query);
4144     ok(r == ERROR_SUCCESS, "failed to add table\n");
4145 
4146     cond = MsiDatabaseIsTablePersistentA(hdb, "T3");
4147     ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4148 
4149     query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4150     r = run_query(hdb, 0, query);
4151     ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
4152 
4153     cond = MsiDatabaseIsTablePersistentA(hdb, "T4");
4154     ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4155 
4156     query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
4157     r = run_query(hdb, 0, query);
4158     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
4159 
4160     query = "select * from `T`";
4161     r = MsiDatabaseOpenViewA(hdb, query, &view);
4162     ok(r == ERROR_SUCCESS, "failed to query table\n");
4163     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4164     ok(r == ERROR_SUCCESS, "failed to get column info\n");
4165 
4166     sz = sizeof buf;
4167     r = MsiRecordGetStringA(rec, 1, buf, &sz);
4168     ok(r == ERROR_SUCCESS, "failed to get string\n");
4169     ok( 0 == strcmp("G255", buf), "wrong column type\n");
4170 
4171     sz = sizeof buf;
4172     r = MsiRecordGetStringA(rec, 2, buf, &sz);
4173     ok(r == ERROR_SUCCESS, "failed to get string\n");
4174     ok( 0 == strcmp("j2", buf), "wrong column type\n");
4175 
4176     MsiCloseHandle( rec );
4177     MsiViewClose( view );
4178     MsiCloseHandle( view );
4179 
4180     /* query the table data */
4181     rec = 0;
4182     r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
4183     ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
4184     MsiCloseHandle( rec );
4185 
4186     /* query the column data */
4187     rec = 0;
4188     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
4189     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4190     if (rec) MsiCloseHandle( rec );
4191 
4192     r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
4193     ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4194     if (rec) MsiCloseHandle( rec );
4195 
4196     MsiCloseHandle( hdb );
4197     DeleteFileA(msifile);
4198 }
4199 
4200 static void test_alter(void)
4201 {
4202     MSICONDITION cond;
4203     MSIHANDLE hdb = 0;
4204     const char *query;
4205     UINT r;
4206 
4207     hdb = create_db();
4208     ok( hdb, "failed to create db\n");
4209 
4210     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4211     r = run_query(hdb, 0, query);
4212     ok(r == ERROR_SUCCESS, "failed to add table\n");
4213 
4214     cond = MsiDatabaseIsTablePersistentA(hdb, "T");
4215     ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4216 
4217     query = "ALTER TABLE `T` HOLD";
4218     r = run_query(hdb, 0, query);
4219     ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4220 
4221     query = "ALTER TABLE `T` FREE";
4222     r = run_query(hdb, 0, query);
4223     ok(r == ERROR_SUCCESS, "failed to free table\n");
4224 
4225     query = "ALTER TABLE `T` FREE";
4226     r = run_query(hdb, 0, query);
4227     ok(r == ERROR_SUCCESS, "failed to free table\n");
4228 
4229     query = "ALTER TABLE `T` FREE";
4230     r = run_query(hdb, 0, query);
4231     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4232 
4233     query = "ALTER TABLE `T` HOLD";
4234     r = run_query(hdb, 0, query);
4235     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4236 
4237     /* table T is removed */
4238     query = "SELECT * FROM `T`";
4239     r = run_query(hdb, 0, query);
4240     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4241 
4242     /* create the table again */
4243     query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4244     r = run_query(hdb, 0, query);
4245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4246 
4247     /* up the ref count */
4248     query = "ALTER TABLE `U` HOLD";
4249     r = run_query(hdb, 0, query);
4250     ok(r == ERROR_SUCCESS, "failed to free table\n");
4251 
4252     /* add column, no data type */
4253     query = "ALTER TABLE `U` ADD `C`";
4254     r = run_query(hdb, 0, query);
4255     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4256 
4257     query = "ALTER TABLE `U` ADD `C` INTEGER";
4258     r = run_query(hdb, 0, query);
4259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4260 
4261     /* add column C again */
4262     query = "ALTER TABLE `U` ADD `C` INTEGER";
4263     r = run_query(hdb, 0, query);
4264     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4265 
4266     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4267     r = run_query(hdb, 0, query);
4268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4269 
4270     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4271     r = run_query(hdb, 0, query);
4272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4273 
4274     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4275     r = run_query(hdb, 0, query);
4276     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4277 
4278     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4279     r = run_query(hdb, 0, query);
4280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4281 
4282     query = "SELECT * FROM `U` WHERE `D` = 8";
4283     r = run_query(hdb, 0, query);
4284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4285 
4286     query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4287     r = run_query(hdb, 0, query);
4288     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4289 
4290     query = "ALTER COLUMN `D` FREE";
4291     r = run_query(hdb, 0, query);
4292     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4293 
4294     /* drop the ref count */
4295     query = "ALTER TABLE `U` FREE";
4296     r = run_query(hdb, 0, query);
4297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4298 
4299     /* table is not empty */
4300     query = "SELECT * FROM `U`";
4301     r = run_query(hdb, 0, query);
4302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4303 
4304     /* column D is removed */
4305     query = "SELECT * FROM `U` WHERE `D` = 8";
4306     r = run_query(hdb, 0, query);
4307     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4308 
4309     query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4310     r = run_query(hdb, 0, query);
4311     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4312 
4313     /* add the column again */
4314     query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4315     r = run_query(hdb, 0, query);
4316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4317 
4318     /* up the ref count */
4319     query = "ALTER TABLE `U` HOLD";
4320     r = run_query(hdb, 0, query);
4321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4322 
4323     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4324     r = run_query(hdb, 0, query);
4325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4326 
4327     query = "SELECT * FROM `U` WHERE `E` = 16";
4328     r = run_query(hdb, 0, query);
4329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4330 
4331     /* drop the ref count */
4332     query = "ALTER TABLE `U` FREE";
4333     r = run_query(hdb, 0, query);
4334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4335 
4336     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4337     r = run_query(hdb, 0, query);
4338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4339 
4340     query = "SELECT * FROM `U` WHERE `E` = 20";
4341     r = run_query(hdb, 0, query);
4342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4343 
4344     /* drop the ref count */
4345     query = "ALTER TABLE `U` FREE";
4346     r = run_query(hdb, 0, query);
4347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4348 
4349     /* table still exists */
4350     query = "SELECT * FROM `U`";
4351     r = run_query(hdb, 0, query);
4352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4353 
4354     /* col E is removed */
4355     query = "SELECT * FROM `U` WHERE `E` = 20";
4356     r = run_query(hdb, 0, query);
4357     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4358 
4359     query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4360     r = run_query(hdb, 0, query);
4361     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4362 
4363     /* drop the ref count once more */
4364     query = "ALTER TABLE `U` FREE";
4365     r = run_query(hdb, 0, query);
4366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4367 
4368     /* table still exists */
4369     query = "SELECT * FROM `U`";
4370     r = run_query(hdb, 0, query);
4371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4372 
4373     MsiCloseHandle( hdb );
4374     DeleteFileA(msifile);
4375 }
4376 
4377 static void test_integers(void)
4378 {
4379     MSIHANDLE hdb = 0, view = 0, rec = 0;
4380     DWORD count, i;
4381     const char *query;
4382     UINT r;
4383 
4384     /* just MsiOpenDatabase should not create a file */
4385     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4386     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4387 
4388     /* create a table */
4389     query = "CREATE TABLE `integers` ( "
4390             "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4391             "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4392             "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4393             "PRIMARY KEY `one`)";
4394     r = MsiDatabaseOpenViewA(hdb, query, &view);
4395     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4396     r = MsiViewExecute(view, 0);
4397     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4398     r = MsiViewClose(view);
4399     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4400     r = MsiCloseHandle(view);
4401     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4402 
4403     query = "SELECT * FROM `integers`";
4404     r = MsiDatabaseOpenViewA(hdb, query, &view);
4405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4406 
4407     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4409     count = MsiRecordGetFieldCount(rec);
4410     ok(count == 8, "Expected 8, got %d\n", count);
4411     ok(check_record(rec, 1, "one"), "Expected one\n");
4412     ok(check_record(rec, 2, "two"), "Expected two\n");
4413     ok(check_record(rec, 3, "three"), "Expected three\n");
4414     ok(check_record(rec, 4, "four"), "Expected four\n");
4415     ok(check_record(rec, 5, "five"), "Expected five\n");
4416     ok(check_record(rec, 6, "six"), "Expected six\n");
4417     ok(check_record(rec, 7, "seven"), "Expected seven\n");
4418     ok(check_record(rec, 8, "eight"), "Expected eight\n");
4419     MsiCloseHandle(rec);
4420 
4421     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4423     count = MsiRecordGetFieldCount(rec);
4424     ok(count == 8, "Expected 8, got %d\n", count);
4425     ok(check_record(rec, 1, "I2"), "Expected I2\n");
4426     ok(check_record(rec, 2, "I2"), "Expected I2\n");
4427     ok(check_record(rec, 3, "I2"), "Expected I2\n");
4428     ok(check_record(rec, 4, "I4"), "Expected I4\n");
4429     ok(check_record(rec, 5, "i2"), "Expected i2\n");
4430     ok(check_record(rec, 6, "i2"), "Expected i2\n");
4431     ok(check_record(rec, 7, "i2"), "Expected i2\n");
4432     ok(check_record(rec, 8, "i4"), "Expected i4\n");
4433     MsiCloseHandle(rec);
4434 
4435     MsiViewClose(view);
4436     MsiCloseHandle(view);
4437 
4438     /* insert values into it, NULL where NOT NULL is specified */
4439     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4440         "VALUES('', '', '', '', '', '', '', '')";
4441     r = MsiDatabaseOpenViewA(hdb, query, &view);
4442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4443     r = MsiViewExecute(view, 0);
4444     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4445 
4446     MsiViewClose(view);
4447     MsiCloseHandle(view);
4448 
4449     query = "SELECT * FROM `integers`";
4450     r = do_query(hdb, query, &rec);
4451     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4452 
4453     r = MsiRecordGetFieldCount(rec);
4454     ok(r == -1, "record count wrong: %d\n", r);
4455 
4456     MsiCloseHandle(rec);
4457 
4458     /* insert legitimate values into it */
4459     query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4460         "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4461     r = MsiDatabaseOpenViewA(hdb, query, &view);
4462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4463     r = MsiViewExecute(view, 0);
4464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4465 
4466     query = "SELECT * FROM `integers`";
4467     r = do_query(hdb, query, &rec);
4468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4469 
4470     r = MsiRecordGetFieldCount(rec);
4471     ok(r == 8, "record count wrong: %d\n", r);
4472 
4473     i = MsiRecordGetInteger(rec, 1);
4474     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4475     i = MsiRecordGetInteger(rec, 3);
4476     ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4477     i = MsiRecordGetInteger(rec, 2);
4478     ok(i == 2, "Expected 2, got %d\n", i);
4479     i = MsiRecordGetInteger(rec, 4);
4480     ok(i == 4, "Expected 4, got %d\n", i);
4481     i = MsiRecordGetInteger(rec, 5);
4482     ok(i == 5, "Expected 5, got %d\n", i);
4483     i = MsiRecordGetInteger(rec, 6);
4484     ok(i == 6, "Expected 6, got %d\n", i);
4485     i = MsiRecordGetInteger(rec, 7);
4486     ok(i == 7, "Expected 7, got %d\n", i);
4487     i = MsiRecordGetInteger(rec, 8);
4488     ok(i == 8, "Expected 8, got %d\n", i);
4489 
4490     MsiCloseHandle(rec);
4491     MsiViewClose(view);
4492     MsiCloseHandle(view);
4493 
4494     r = MsiDatabaseCommit(hdb);
4495     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4496 
4497     r = MsiCloseHandle(hdb);
4498     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4499 
4500     r = DeleteFileA(msifile);
4501     ok(r == TRUE, "file didn't exist after commit\n");
4502 }
4503 
4504 static void test_update(void)
4505 {
4506     MSIHANDLE hdb = 0, view = 0, rec = 0;
4507     CHAR result[MAX_PATH];
4508     const char *query;
4509     DWORD size;
4510     UINT r;
4511 
4512     /* just MsiOpenDatabase should not create a file */
4513     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4514     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4515 
4516     /* create the Control table */
4517     query = "CREATE TABLE `Control` ( "
4518         "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4519         "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4520         "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4521         "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4522     r = MsiDatabaseOpenViewA(hdb, query, &view);
4523     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4524     r = MsiViewExecute(view, 0);
4525     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4526     r = MsiViewClose(view);
4527     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4528     r = MsiCloseHandle(view);
4529     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4530 
4531     /* add a control */
4532     query = "INSERT INTO `Control` ( "
4533         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4534         "`Property`, `Text`, `Control_Next`, `Help` )"
4535         "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4536     r = MsiDatabaseOpenViewA(hdb, query, &view);
4537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4538     r = MsiViewExecute(view, 0);
4539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4540     r = MsiViewClose(view);
4541     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4542     r = MsiCloseHandle(view);
4543     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4544 
4545     /* add a second control */
4546     query = "INSERT INTO `Control` ( "
4547         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4548         "`Property`, `Text`, `Control_Next`, `Help` )"
4549         "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4550     r = MsiDatabaseOpenViewA(hdb, query, &view);
4551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4552     r = MsiViewExecute(view, 0);
4553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4554     r = MsiViewClose(view);
4555     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4556     r = MsiCloseHandle(view);
4557     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4558 
4559     /* add a third control */
4560     query = "INSERT INTO `Control` ( "
4561         "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4562         "`Property`, `Text`, `Control_Next`, `Help` )"
4563         "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4564     r = MsiDatabaseOpenViewA(hdb, query, &view);
4565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4566     r = MsiViewExecute(view, 0);
4567     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4568     r = MsiViewClose(view);
4569     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4570     r = MsiCloseHandle(view);
4571     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4572 
4573     /* bad table */
4574     query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4575     r = MsiDatabaseOpenViewA(hdb, query, &view);
4576     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4577 
4578     /* bad set column */
4579     query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4580     r = MsiDatabaseOpenViewA(hdb, query, &view);
4581     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4582 
4583     /* bad where condition */
4584     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4585     r = MsiDatabaseOpenViewA(hdb, query, &view);
4586     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4587 
4588     /* just the dialog_ specified */
4589     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4590     r = MsiDatabaseOpenViewA(hdb, query, &view);
4591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4592     r = MsiViewExecute(view, 0);
4593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4594     r = MsiViewClose(view);
4595     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4596     r = MsiCloseHandle(view);
4597     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4598 
4599     /* check the modified text */
4600     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4601     r = MsiDatabaseOpenViewA(hdb, query, &view);
4602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4603     r = MsiViewExecute(view, 0);
4604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4605 
4606     r = MsiViewFetch(view, &rec);
4607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4608 
4609     size = MAX_PATH;
4610     r = MsiRecordGetStringA(rec, 1, result, &size);
4611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4612     ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4613 
4614     MsiCloseHandle(rec);
4615 
4616     r = MsiViewFetch(view, &rec);
4617     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4618 
4619     size = MAX_PATH;
4620     r = MsiRecordGetStringA(rec, 1, result, &size);
4621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4622     ok(!result[0], "Expected an empty string, got %s\n", result);
4623 
4624     MsiCloseHandle(rec);
4625 
4626     r = MsiViewFetch(view, &rec);
4627     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4628 
4629     r = MsiViewClose(view);
4630     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4631     r = MsiCloseHandle(view);
4632     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4633 
4634     /* dialog_ and control specified */
4635     query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4636     r = MsiDatabaseOpenViewA(hdb, query, &view);
4637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4638     r = MsiViewExecute(view, 0);
4639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4640     r = MsiViewClose(view);
4641     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4642     r = MsiCloseHandle(view);
4643     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4644 
4645     /* check the modified text */
4646     query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4647     r = MsiDatabaseOpenViewA(hdb, query, &view);
4648     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4649     r = MsiViewExecute(view, 0);
4650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4651 
4652     r = MsiViewFetch(view, &rec);
4653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4654 
4655     size = MAX_PATH;
4656     r = MsiRecordGetStringA(rec, 1, result, &size);
4657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4658     ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4659 
4660     MsiCloseHandle(rec);
4661 
4662     r = MsiViewFetch(view, &rec);
4663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4664 
4665     size = MAX_PATH;
4666     r = MsiRecordGetStringA(rec, 1, result, &size);
4667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4668     ok(!result[0], "Expected an empty string, got %s\n", result);
4669 
4670     MsiCloseHandle(rec);
4671 
4672     r = MsiViewFetch(view, &rec);
4673     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4674 
4675     r = MsiViewClose(view);
4676     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4677     r = MsiCloseHandle(view);
4678     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4679 
4680     /* no where condition */
4681     query = "UPDATE `Control` SET `Text` = 'this is text'";
4682     r = MsiDatabaseOpenViewA(hdb, query, &view);
4683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4684     r = MsiViewExecute(view, 0);
4685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4686     r = MsiViewClose(view);
4687     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4688     r = MsiCloseHandle(view);
4689     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4690 
4691     /* check the modified text */
4692     query = "SELECT `Text` FROM `Control`";
4693     r = MsiDatabaseOpenViewA(hdb, query, &view);
4694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4695     r = MsiViewExecute(view, 0);
4696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4697 
4698     r = MsiViewFetch(view, &rec);
4699     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4700 
4701     size = MAX_PATH;
4702     r = MsiRecordGetStringA(rec, 1, result, &size);
4703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4704     ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4705 
4706     MsiCloseHandle(rec);
4707 
4708     r = MsiViewFetch(view, &rec);
4709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4710 
4711     size = MAX_PATH;
4712     r = MsiRecordGetStringA(rec, 1, result, &size);
4713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4714     ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4715 
4716     MsiCloseHandle(rec);
4717 
4718     r = MsiViewFetch(view, &rec);
4719     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4720 
4721     size = MAX_PATH;
4722     r = MsiRecordGetStringA(rec, 1, result, &size);
4723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4724     ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4725 
4726     MsiCloseHandle(rec);
4727 
4728     r = MsiViewFetch(view, &rec);
4729     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4730 
4731     r = MsiViewClose(view);
4732     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4733     r = MsiCloseHandle(view);
4734     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4735 
4736     query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4737         "`Orange` CHAR(72),  `Pear` INT PRIMARY KEY `Banana`)";
4738     r = run_query(hdb, 0, query);
4739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4740 
4741     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4742         "VALUES('one', 'two', 3)";
4743     r = run_query(hdb, 0, query);
4744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4745 
4746     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4747         "VALUES('three', 'four', 5)";
4748     r = run_query(hdb, 0, query);
4749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4750 
4751     query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4752         "VALUES('six', 'two', 7)";
4753     r = run_query(hdb, 0, query);
4754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4755 
4756     rec = MsiCreateRecord(2);
4757     MsiRecordSetInteger(rec, 1, 8);
4758     MsiRecordSetStringA(rec, 2, "two");
4759 
4760     query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4761     r = run_query(hdb, rec, query);
4762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4763 
4764     MsiCloseHandle(rec);
4765 
4766     query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4767     r = MsiDatabaseOpenViewA(hdb, query, &view);
4768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4769     r = MsiViewExecute(view, 0);
4770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4771 
4772     r = MsiViewFetch(view, &rec);
4773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4774 
4775     r = MsiRecordGetInteger(rec, 1);
4776     ok(r == 8, "Expected 8, got %d\n", r);
4777 
4778     MsiCloseHandle(rec);
4779 
4780     r = MsiViewFetch(view, &rec);
4781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4782 
4783     r = MsiRecordGetInteger(rec, 1);
4784     ok(r == 8, "Expected 8, got %d\n", r);
4785 
4786     MsiCloseHandle(rec);
4787 
4788     r = MsiViewFetch(view, &rec);
4789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4790 
4791     r = MsiRecordGetInteger(rec, 1);
4792     ok(r == 5, "Expected 5, got %d\n", r);
4793 
4794     MsiCloseHandle(rec);
4795 
4796     r = MsiViewFetch(view, &rec);
4797     ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4798 
4799     MsiViewClose(view);
4800     MsiCloseHandle(view);
4801 
4802     r = MsiDatabaseCommit(hdb);
4803     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4804     r = MsiCloseHandle(hdb);
4805     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4806 
4807     DeleteFileA(msifile);
4808 }
4809 
4810 static void test_special_tables(void)
4811 {
4812     const char *query;
4813     MSIHANDLE hdb = 0;
4814     UINT r;
4815 
4816     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4817     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4818 
4819     query = "CREATE TABLE `_Properties` ( "
4820         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4821     r = run_query(hdb, 0, query);
4822     ok(r == ERROR_SUCCESS, "failed to create table\n");
4823 
4824     query = "CREATE TABLE `_Storages` ( "
4825         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4826     r = run_query(hdb, 0, query);
4827     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4828 
4829     query = "CREATE TABLE `_Streams` ( "
4830         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4831     r = run_query(hdb, 0, query);
4832     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4833 
4834     query = "CREATE TABLE `_Tables` ( "
4835         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4836     r = run_query(hdb, 0, query);
4837     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4838 
4839     query = "CREATE TABLE `_Columns` ( "
4840         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4841     r = run_query(hdb, 0, query);
4842     ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4843 
4844     r = MsiCloseHandle(hdb);
4845     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4846 }
4847 
4848 static void test_tables_order(void)
4849 {
4850     const char *query;
4851     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4852     UINT r;
4853     char buffer[100];
4854     DWORD sz;
4855 
4856     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4857     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4858 
4859     query = "CREATE TABLE `foo` ( "
4860         "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4861     r = run_query(hdb, 0, query);
4862     ok(r == ERROR_SUCCESS, "failed to create table\n");
4863 
4864     query = "CREATE TABLE `bar` ( "
4865         "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4866     r = run_query(hdb, 0, query);
4867     ok(r == ERROR_SUCCESS, "failed to create table\n");
4868 
4869     query = "CREATE TABLE `baz` ( "
4870         "`bar` INT NOT NULL, "
4871         "`baz` INT NOT NULL, "
4872         "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4873     r = run_query(hdb, 0, query);
4874     ok(r == ERROR_SUCCESS, "failed to create table\n");
4875 
4876     /* The names of the tables in the _Tables table must
4877        be in the same order as these names are created in
4878        the strings table. */
4879     query = "SELECT * FROM `_Tables`";
4880     r = MsiDatabaseOpenViewA(hdb, query, &hview);
4881     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4882     r = MsiViewExecute(hview, 0);
4883     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4884 
4885     r = MsiViewFetch(hview, &hrec);
4886     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4887     sz = sizeof(buffer);
4888     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4890     ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4891     r = MsiCloseHandle(hrec);
4892     ok(r == ERROR_SUCCESS, "failed to close record\n");
4893 
4894     r = MsiViewFetch(hview, &hrec);
4895     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4896     sz = sizeof(buffer);
4897     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4899     ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4900     r = MsiCloseHandle(hrec);
4901     ok(r == ERROR_SUCCESS, "failed to close record\n");
4902 
4903     r = MsiViewFetch(hview, &hrec);
4904     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4905     sz = sizeof(buffer);
4906     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4908     ok(!lstrcmpA(buffer, "bar"), "Expected bar, got %s\n", buffer);
4909     r = MsiCloseHandle(hrec);
4910     ok(r == ERROR_SUCCESS, "failed to close record\n");
4911 
4912     r = MsiViewClose(hview);
4913     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4914     r = MsiCloseHandle(hview);
4915     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4916 
4917     /* The names of the tables in the _Columns table must
4918        be in the same order as these names are created in
4919        the strings table. */
4920     query = "SELECT * FROM `_Columns`";
4921     r = MsiDatabaseOpenViewA(hdb, query, &hview);
4922     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4923     r = MsiViewExecute(hview, 0);
4924     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4925 
4926     r = MsiViewFetch(hview, &hrec);
4927     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4928     sz = sizeof(buffer);
4929     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4931     ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4932     sz = sizeof(buffer);
4933     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4934     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4935     ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4936     r = MsiCloseHandle(hrec);
4937     ok(r == ERROR_SUCCESS, "failed to close record\n");
4938 
4939     r = MsiViewFetch(hview, &hrec);
4940     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4941     sz = sizeof(buffer);
4942     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4944     ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4945     sz = sizeof(buffer);
4946     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4948     ok(!lstrcmpA(buffer, "bar"), "Expected bar, got %s\n", buffer);
4949     r = MsiCloseHandle(hrec);
4950     ok(r == ERROR_SUCCESS, "failed to close record\n");
4951 
4952     r = MsiViewFetch(hview, &hrec);
4953     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4954     sz = sizeof(buffer);
4955     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4957     ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4958     sz = sizeof(buffer);
4959     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4961     ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4962     r = MsiCloseHandle(hrec);
4963     ok(r == ERROR_SUCCESS, "failed to close record\n");
4964 
4965     r = MsiViewFetch(hview, &hrec);
4966     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4967     sz = sizeof(buffer);
4968     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4970     ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4971     sz = sizeof(buffer);
4972     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4974     ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4975     r = MsiCloseHandle(hrec);
4976     ok(r == ERROR_SUCCESS, "failed to close record\n");
4977 
4978     r = MsiViewFetch(hview, &hrec);
4979     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4980     sz = sizeof(buffer);
4981     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4982     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4983     ok(!lstrcmpA(buffer, "bar"), "Expected bar, got %s\n", buffer);
4984     sz = sizeof(buffer);
4985     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4987     ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4988     r = MsiCloseHandle(hrec);
4989     ok(r == ERROR_SUCCESS, "failed to close record\n");
4990 
4991     r = MsiViewClose(hview);
4992     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4993     r = MsiCloseHandle(hview);
4994     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4995 
4996     r = MsiCloseHandle(hdb);
4997     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4998 
4999     DeleteFileA(msifile);
5000 }
5001 
5002 static void test_rows_order(void)
5003 {
5004     const char *query;
5005     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5006     UINT r;
5007     char buffer[100];
5008     DWORD sz;
5009 
5010     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5011     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5012 
5013     query = "CREATE TABLE `foo` ( "
5014         "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
5015     r = run_query(hdb, 0, query);
5016     ok(r == ERROR_SUCCESS, "failed to create table\n");
5017 
5018     r = run_query(hdb, 0, "INSERT INTO `foo` "
5019             "( `bar` ) VALUES ( 'A' )");
5020     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5021 
5022     r = run_query(hdb, 0, "INSERT INTO `foo` "
5023             "( `bar` ) VALUES ( 'B' )");
5024     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5025 
5026     r = run_query(hdb, 0, "INSERT INTO `foo` "
5027             "( `bar` ) VALUES ( 'C' )");
5028     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5029 
5030     r = run_query(hdb, 0, "INSERT INTO `foo` "
5031             "( `bar` ) VALUES ( 'D' )");
5032     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5033 
5034     r = run_query(hdb, 0, "INSERT INTO `foo` "
5035             "( `bar` ) VALUES ( 'E' )");
5036     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5037 
5038     r = run_query(hdb, 0, "INSERT INTO `foo` "
5039             "( `bar` ) VALUES ( 'F' )");
5040     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5041 
5042     query = "CREATE TABLE `bar` ( "
5043         "`foo` LONGCHAR NOT NULL, "
5044         "`baz` LONGCHAR NOT NULL "
5045         "PRIMARY KEY `foo` )";
5046     r = run_query(hdb, 0, query);
5047     ok(r == ERROR_SUCCESS, "failed to create table\n");
5048 
5049     r = run_query(hdb, 0, "INSERT INTO `bar` "
5050             "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
5051     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5052 
5053     r = run_query(hdb, 0, "INSERT INTO `bar` "
5054             "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
5055     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5056 
5057     r = run_query(hdb, 0, "INSERT INTO `bar` "
5058             "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
5059     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5060 
5061     r = run_query(hdb, 0, "INSERT INTO `bar` "
5062             "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
5063     ok(r == ERROR_SUCCESS, "cannot add value to table\n");
5064 
5065     /* The rows of the table must be ordered by the column values of
5066        each row. For strings, the column value is the string id
5067        in the string table.  */
5068 
5069     query = "SELECT * FROM `bar`";
5070     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5071     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5072     r = MsiViewExecute(hview, 0);
5073     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5074 
5075     r = MsiViewFetch(hview, &hrec);
5076     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5077     sz = sizeof(buffer);
5078     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5080     ok(!lstrcmpA(buffer, "A"), "Expected A, got %s\n", buffer);
5081     sz = sizeof(buffer);
5082     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5083     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5084     ok(!lstrcmpA(buffer, "B"), "Expected B, got %s\n", buffer);
5085     r = MsiCloseHandle(hrec);
5086     ok(r == ERROR_SUCCESS, "failed to close record\n");
5087 
5088     r = MsiViewFetch(hview, &hrec);
5089     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5090     sz = sizeof(buffer);
5091     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5093     ok(!lstrcmpA(buffer, "C"), "Expected E, got %s\n", buffer);
5094     sz = sizeof(buffer);
5095     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5096     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5097     ok(!lstrcmpA(buffer, "E"), "Expected E, got %s\n", buffer);
5098     r = MsiCloseHandle(hrec);
5099     ok(r == ERROR_SUCCESS, "failed to close record\n");
5100 
5101     r = MsiViewFetch(hview, &hrec);
5102     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5103     sz = sizeof(buffer);
5104     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5106     ok(!lstrcmpA(buffer, "D"), "Expected D, got %s\n", buffer);
5107     sz = sizeof(buffer);
5108     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5110     ok(!lstrcmpA(buffer, "E"), "Expected E, got %s\n", buffer);
5111     r = MsiCloseHandle(hrec);
5112     ok(r == ERROR_SUCCESS, "failed to close record\n");
5113 
5114     r = MsiViewFetch(hview, &hrec);
5115     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5116     sz = sizeof(buffer);
5117     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5119     ok(!lstrcmpA(buffer, "F"), "Expected F, got %s\n", buffer);
5120     sz = sizeof(buffer);
5121     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5123     ok(!lstrcmpA(buffer, "A"), "Expected A, got %s\n", buffer);
5124     r = MsiCloseHandle(hrec);
5125     ok(r == ERROR_SUCCESS, "failed to close record\n");
5126 
5127     r = MsiViewClose(hview);
5128     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5129     r = MsiCloseHandle(hview);
5130     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5131 
5132     r = MsiCloseHandle(hdb);
5133     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5134 
5135     DeleteFileA(msifile);
5136 }
5137 
5138 static void test_collation(void)
5139 {
5140     static const WCHAR query1[] =
5141         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5142          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5143          '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
5144     static const WCHAR query2[] =
5145         {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5146          '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5147          '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
5148     static const WCHAR query3[] =
5149         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
5150          '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
5151            ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
5152            'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
5153     static const WCHAR query4[] =
5154         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
5155          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5156          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5157     static const WCHAR query5[] =
5158         {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
5159          '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5160          'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5161     static const WCHAR query6[] =
5162         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
5163          ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
5164     static const WCHAR letter_C[] = {'C',0};
5165     static const WCHAR letter_D[] = {'D',0};
5166     static const WCHAR letter_a_ring[] = {'a',0x30a,0};
5167     static const WCHAR letter_a_with_ring[] = {0xe5,0};
5168     const char *query;
5169     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5170     UINT r;
5171     char buffer[100];
5172     WCHAR bufferW[100];
5173     DWORD sz;
5174 
5175     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5176     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5177 
5178     query = "CREATE TABLE `bar` ( "
5179         "`foo` LONGCHAR NOT NULL, "
5180         "`baz` LONGCHAR NOT NULL "
5181         "PRIMARY KEY `foo` )";
5182     r = run_query(hdb, 0, query);
5183     ok(r == ERROR_SUCCESS, "failed to create table\n");
5184 
5185     r = run_query(hdb, 0, query);
5186     ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
5187 
5188     r = run_query(hdb, 0, "INSERT INTO `bar` "
5189             "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
5190     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5191 
5192     r = run_query(hdb, 0, "INSERT INTO `bar` "
5193             "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
5194     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5195 
5196     r = run_queryW(hdb, 0, query1);
5197     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5198 
5199     r = run_queryW(hdb, 0, query2);
5200     ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5201 
5202     r = run_queryW(hdb, 0, query3);
5203     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5204 
5205     r = run_queryW(hdb, 0, query4);
5206     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5207 
5208     r = run_queryW(hdb, 0, query5);
5209     ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5210 
5211     query = "SELECT * FROM `bar`";
5212     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5213     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5214     r = MsiViewExecute(hview, 0);
5215     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5216 
5217     r = MsiViewFetch(hview, &hrec);
5218     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5219     sz = sizeof(buffer);
5220     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5222     ok(!lstrcmpA(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
5223     sz = sizeof(buffer);
5224     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5226     ok(!lstrcmpA(buffer, "A"), "Expected A, got '%s'\n", buffer);
5227     MsiCloseHandle(hrec);
5228 
5229     r = MsiViewFetch(hview, &hrec);
5230     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5231     sz = sizeof(buffer);
5232     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5234     ok(!lstrcmpA(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
5235     sz = sizeof(buffer);
5236     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5237     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5238     ok(!lstrcmpA(buffer, "B"), "Expected B, got '%s'\n", buffer);
5239     MsiCloseHandle(hrec);
5240 
5241     r = MsiViewFetch(hview, &hrec);
5242     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5243     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5244     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5246     ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)),
5247        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
5248     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5249     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5251     ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
5252     MsiCloseHandle(hrec);
5253 
5254     r = MsiViewFetch(hview, &hrec);
5255     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5256     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5257     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5259     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5260        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5261     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5262     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5264     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5265     MsiCloseHandle(hrec);
5266 
5267     r = MsiViewClose(hview);
5268     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5269     r = MsiCloseHandle(hview);
5270     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5271 
5272     r = MsiDatabaseOpenViewW(hdb, query6, &hview);
5273     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5274     r = MsiViewExecute(hview, 0);
5275     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5276 
5277     r = MsiViewFetch(hview, &hrec);
5278     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5279     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5280     r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5282     ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5283        "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5284     sz = sizeof(bufferW) / sizeof(bufferW[0]);
5285     r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5287     ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5288     MsiCloseHandle(hrec);
5289 
5290     r = MsiViewFetch(hview, &hrec);
5291     ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
5292 
5293     r = MsiViewClose(hview);
5294     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5295     r = MsiCloseHandle(hview);
5296     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5297 
5298     r = MsiCloseHandle(hdb);
5299     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5300 
5301     DeleteFileA(msifile);
5302 }
5303 
5304 static void test_select_markers(void)
5305 {
5306     MSIHANDLE hdb = 0, rec, view, res;
5307     LPCSTR query;
5308     UINT r;
5309     DWORD size;
5310     CHAR buf[MAX_PATH];
5311 
5312     hdb = create_db();
5313     ok( hdb, "failed to create db\n");
5314 
5315     r = run_query(hdb, 0,
5316             "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
5317     ok(r == S_OK, "cannot create table: %d\n", r);
5318 
5319     r = run_query(hdb, 0, "INSERT INTO `Table` "
5320             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
5321     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5322 
5323     r = run_query(hdb, 0, "INSERT INTO `Table` "
5324             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
5325     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5326 
5327     r = run_query(hdb, 0, "INSERT INTO `Table` "
5328             "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
5329     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5330 
5331     r = run_query(hdb, 0, "INSERT INTO `Table` "
5332             "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
5333     ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5334 
5335     rec = MsiCreateRecord(2);
5336     MsiRecordSetStringA(rec, 1, "apple");
5337     MsiRecordSetStringA(rec, 2, "two");
5338 
5339     query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
5340     r = MsiDatabaseOpenViewA(hdb, query, &view);
5341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5342 
5343     r = MsiViewExecute(view, rec);
5344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5345 
5346     r = MsiViewFetch(view, &res);
5347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5348 
5349     size = MAX_PATH;
5350     r = MsiRecordGetStringA(res, 1, buf, &size);
5351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5352     ok(!lstrcmpA(buf, "apple"), "Expected apple, got %s\n", buf);
5353 
5354     size = MAX_PATH;
5355     r = MsiRecordGetStringA(res, 2, buf, &size);
5356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5357     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
5358 
5359     r = MsiRecordGetInteger(res, 3);
5360     ok(r == 1, "Expected 1, got %d\n", r);
5361 
5362     MsiCloseHandle(res);
5363 
5364     r = MsiViewFetch(view, &res);
5365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5366 
5367     size = MAX_PATH;
5368     r = MsiRecordGetStringA(res, 1, buf, &size);
5369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5370     ok(!lstrcmpA(buf, "apple"), "Expected apple, got %s\n", buf);
5371 
5372     size = MAX_PATH;
5373     r = MsiRecordGetStringA(res, 2, buf, &size);
5374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5375     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
5376 
5377     r = MsiRecordGetInteger(res, 3);
5378     ok(r == 2, "Expected 2, got %d\n", r);
5379 
5380     MsiCloseHandle(res);
5381 
5382     r = MsiViewFetch(view, &res);
5383     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5384 
5385     MsiCloseHandle(rec);
5386     MsiViewClose(view);
5387     MsiCloseHandle(view);
5388 
5389     rec = MsiCreateRecord(2);
5390     MsiRecordSetStringA(rec, 1, "one");
5391     MsiRecordSetInteger(rec, 2, 1);
5392 
5393     query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5394     r = MsiDatabaseOpenViewA(hdb, query, &view);
5395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5396     r = MsiViewExecute(view, rec);
5397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5398 
5399     r = MsiViewFetch(view, &res);
5400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5401 
5402     size = MAX_PATH;
5403     r = MsiRecordGetStringA(res, 1, buf, &size);
5404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5405     ok(!lstrcmpA(buf, "apple"), "Expected apple, got %s\n", buf);
5406 
5407     size = MAX_PATH;
5408     r = MsiRecordGetStringA(res, 2, buf, &size);
5409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5410     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
5411 
5412     r = MsiRecordGetInteger(res, 3);
5413     ok(r == 2, "Expected 2, got %d\n", r);
5414 
5415     MsiCloseHandle(res);
5416 
5417     r = MsiViewFetch(view, &res);
5418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5419 
5420     size = MAX_PATH;
5421     r = MsiRecordGetStringA(res, 1, buf, &size);
5422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5423     ok(!lstrcmpA(buf, "banana"), "Expected banana, got %s\n", buf);
5424 
5425     size = MAX_PATH;
5426     r = MsiRecordGetStringA(res, 2, buf, &size);
5427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5428     ok(!lstrcmpA(buf, "three"), "Expected three, got %s\n", buf);
5429 
5430     r = MsiRecordGetInteger(res, 3);
5431     ok(r == 3, "Expected 3, got %d\n", r);
5432 
5433     MsiCloseHandle(res);
5434 
5435     r = MsiViewFetch(view, &res);
5436     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5437 
5438     MsiCloseHandle(rec);
5439     MsiViewClose(view);
5440     MsiCloseHandle(view);
5441     MsiCloseHandle(hdb);
5442     DeleteFileA(msifile);
5443 }
5444 
5445 static void test_viewmodify_update(void)
5446 {
5447     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5448     UINT i, test_max, offset, count;
5449     const char *query;
5450     UINT r;
5451 
5452     DeleteFileA(msifile);
5453 
5454     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5455     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5456 
5457     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5458     r = run_query( hdb, 0, query );
5459     ok(r == ERROR_SUCCESS, "query failed\n");
5460 
5461     query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5462     r = run_query( hdb, 0, query );
5463     ok(r == ERROR_SUCCESS, "query failed\n");
5464 
5465     query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5466     r = run_query( hdb, 0, query );
5467     ok(r == ERROR_SUCCESS, "query failed\n");
5468 
5469     query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5470     r = run_query( hdb, 0, query );
5471     ok(r == ERROR_SUCCESS, "query failed\n");
5472 
5473     query = "SELECT `B` FROM `table`";
5474     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5475     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5476     r = MsiViewExecute(hview, 0);
5477     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5478     r = MsiViewFetch(hview, &hrec);
5479     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5480 
5481     r = MsiRecordSetInteger(hrec, 1, 0);
5482     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5483 
5484     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5485     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5486 
5487     r = MsiCloseHandle(hrec);
5488     ok(r == ERROR_SUCCESS, "failed to close record\n");
5489 
5490     r = MsiViewClose(hview);
5491     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5492     r = MsiCloseHandle(hview);
5493     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5494 
5495     query = "SELECT * FROM `table`";
5496     r = MsiDatabaseOpenViewA(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     r = MsiViewFetch(hview, &hrec);
5501     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5502 
5503     r = MsiRecordGetInteger(hrec, 1);
5504     ok(r == 1, "Expected 1, got %d\n", r);
5505     r = MsiRecordGetInteger(hrec, 2);
5506     ok(r == 0, "Expected 0, got %d\n", r);
5507 
5508     r = MsiCloseHandle(hrec);
5509     ok(r == ERROR_SUCCESS, "failed to close record\n");
5510 
5511     r = MsiViewFetch(hview, &hrec);
5512     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5513 
5514     r = MsiRecordGetInteger(hrec, 1);
5515     ok(r == 3, "Expected 3, got %d\n", r);
5516     r = MsiRecordGetInteger(hrec, 2);
5517     ok(r == 4, "Expected 4, got %d\n", r);
5518 
5519     r = MsiCloseHandle(hrec);
5520     ok(r == ERROR_SUCCESS, "failed to close record\n");
5521 
5522     r = MsiViewFetch(hview, &hrec);
5523     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5524 
5525     r = MsiRecordGetInteger(hrec, 1);
5526     ok(r == 5, "Expected 5, got %d\n", r);
5527     r = MsiRecordGetInteger(hrec, 2);
5528     ok(r == 6, "Expected 6, got %d\n", r);
5529 
5530     r = MsiCloseHandle(hrec);
5531     ok(r == ERROR_SUCCESS, "failed to close record\n");
5532 
5533     r = MsiViewFetch(hview, &hrec);
5534     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5535 
5536     r = MsiViewClose(hview);
5537     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5538     r = MsiCloseHandle(hview);
5539     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5540 
5541     /* loop through all elements */
5542     query = "SELECT `B` FROM `table`";
5543     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5544     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5545     r = MsiViewExecute(hview, 0);
5546     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5547 
5548     while (TRUE)
5549     {
5550         r = MsiViewFetch(hview, &hrec);
5551         if (r != ERROR_SUCCESS)
5552             break;
5553 
5554         r = MsiRecordSetInteger(hrec, 1, 0);
5555         ok(r == ERROR_SUCCESS, "failed to set integer\n");
5556 
5557         r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5558         ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5559 
5560         r = MsiCloseHandle(hrec);
5561         ok(r == ERROR_SUCCESS, "failed to close record\n");
5562     }
5563 
5564     r = MsiViewClose(hview);
5565     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5566     r = MsiCloseHandle(hview);
5567     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5568 
5569     query = "SELECT * FROM `table`";
5570     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5571     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5572     r = MsiViewExecute(hview, 0);
5573     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5574     r = MsiViewFetch(hview, &hrec);
5575     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5576 
5577     r = MsiRecordGetInteger(hrec, 1);
5578     ok(r == 1, "Expected 1, got %d\n", r);
5579     r = MsiRecordGetInteger(hrec, 2);
5580     ok(r == 0, "Expected 0, got %d\n", r);
5581 
5582     r = MsiCloseHandle(hrec);
5583     ok(r == ERROR_SUCCESS, "failed to close record\n");
5584 
5585     r = MsiViewFetch(hview, &hrec);
5586     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5587 
5588     r = MsiRecordGetInteger(hrec, 1);
5589     ok(r == 3, "Expected 3, got %d\n", r);
5590     r = MsiRecordGetInteger(hrec, 2);
5591     ok(r == 0, "Expected 0, got %d\n", r);
5592 
5593     r = MsiCloseHandle(hrec);
5594     ok(r == ERROR_SUCCESS, "failed to close record\n");
5595 
5596     r = MsiViewFetch(hview, &hrec);
5597     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5598 
5599     r = MsiRecordGetInteger(hrec, 1);
5600     ok(r == 5, "Expected 5, got %d\n", r);
5601     r = MsiRecordGetInteger(hrec, 2);
5602     ok(r == 0, "Expected 0, got %d\n", r);
5603 
5604     r = MsiCloseHandle(hrec);
5605     ok(r == ERROR_SUCCESS, "failed to close record\n");
5606 
5607     r = MsiViewFetch(hview, &hrec);
5608     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5609 
5610     r = MsiViewClose(hview);
5611     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5612     r = MsiCloseHandle(hview);
5613     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5614 
5615     query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5616     r = run_query( hdb, 0, query );
5617     ok(r == ERROR_SUCCESS, "query failed\n");
5618 
5619     query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5620     r = MsiDatabaseOpenViewA( hdb, query, &hview );
5621     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5622 
5623     test_max = 100;
5624     offset = 1234;
5625     for(i = 0; i < test_max; i++)
5626     {
5627 
5628         hrec = MsiCreateRecord( 2 );
5629         MsiRecordSetInteger( hrec, 1, test_max - i );
5630         MsiRecordSetInteger( hrec, 2, i );
5631 
5632         r = MsiViewExecute( hview, hrec );
5633         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5634 
5635         r = MsiCloseHandle( hrec );
5636         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5637     }
5638 
5639     r = MsiViewClose( hview );
5640     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5641     r = MsiCloseHandle( hview );
5642     ok(r == ERROR_SUCCESS, "Got %d\n", r);
5643 
5644     /* Update. */
5645     query = "SELECT * FROM `table2` ORDER BY `B`";
5646     r = MsiDatabaseOpenViewA( hdb, query, &hview);
5647     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5648     r = MsiViewExecute( hview, 0 );
5649     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5650 
5651     count = 0;
5652     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5653     {
5654         UINT b = MsiRecordGetInteger( hrec, 2 );
5655 
5656         r = MsiRecordSetInteger( hrec, 2, b + offset);
5657         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5658 
5659         r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5660         ok(r == ERROR_SUCCESS, "Got %d\n", r);
5661 
5662         r = MsiCloseHandle(hrec);
5663         ok(r == ERROR_SUCCESS, "failed to close record\n");
5664         count++;
5665     }
5666     ok(count == test_max, "Got count %d\n", count);
5667 
5668     r = MsiViewClose(hview);
5669     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5670     r = MsiCloseHandle(hview);
5671     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5672 
5673     /* Recheck. */
5674     query = "SELECT * FROM `table2` ORDER BY `B`";
5675     r = MsiDatabaseOpenViewA( hdb, query, &hview);
5676     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5677     r = MsiViewExecute( hview, 0 );
5678     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5679 
5680     count = 0;
5681     while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5682     {
5683         UINT a = MsiRecordGetInteger( hrec, 1 );
5684         UINT b = MsiRecordGetInteger( hrec, 2 );
5685         ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5686             a, b, test_max - a + offset, b);
5687 
5688         r = MsiCloseHandle(hrec);
5689         ok(r == ERROR_SUCCESS, "failed to close record\n");
5690         count++;
5691     }
5692     ok(count == test_max, "Got count %d\n", count);
5693 
5694     r = MsiViewClose(hview);
5695     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5696     r = MsiCloseHandle(hview);
5697     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5698 
5699     r = MsiCloseHandle( hdb );
5700     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5701 }
5702 
5703 static void test_viewmodify_assign(void)
5704 {
5705     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5706     const char *query;
5707     UINT r;
5708 
5709     /* setup database */
5710     DeleteFileA(msifile);
5711 
5712     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5713     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5714 
5715     query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5716     r = run_query( hdb, 0, query );
5717     ok(r == ERROR_SUCCESS, "query failed\n");
5718 
5719     /* assign to view, new primary key */
5720     query = "SELECT * FROM `table`";
5721     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5722     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5723     r = MsiViewExecute(hview, 0);
5724     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5725 
5726     hrec = MsiCreateRecord(2);
5727     ok(hrec != 0, "MsiCreateRecord failed\n");
5728 
5729     r = MsiRecordSetInteger(hrec, 1, 1);
5730     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5731     r = MsiRecordSetInteger(hrec, 2, 2);
5732     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5733 
5734     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5735     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5736 
5737     r = MsiCloseHandle(hrec);
5738     ok(r == ERROR_SUCCESS, "failed to close record\n");
5739 
5740     r = MsiViewClose(hview);
5741     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5742     r = MsiCloseHandle(hview);
5743     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5744 
5745     query = "SELECT * FROM `table`";
5746     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5747     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5748     r = MsiViewExecute(hview, 0);
5749     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5750     r = MsiViewFetch(hview, &hrec);
5751     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5752 
5753     r = MsiRecordGetInteger(hrec, 1);
5754     ok(r == 1, "Expected 1, got %d\n", r);
5755     r = MsiRecordGetInteger(hrec, 2);
5756     ok(r == 2, "Expected 2, got %d\n", r);
5757 
5758     r = MsiCloseHandle(hrec);
5759     ok(r == ERROR_SUCCESS, "failed to close record\n");
5760 
5761     r = MsiViewFetch(hview, &hrec);
5762     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5763 
5764     r = MsiViewClose(hview);
5765     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5766     r = MsiCloseHandle(hview);
5767     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5768 
5769     /* assign to view, primary key matches */
5770     query = "SELECT * FROM `table`";
5771     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5772     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5773     r = MsiViewExecute(hview, 0);
5774     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5775 
5776     hrec = MsiCreateRecord(2);
5777     ok(hrec != 0, "MsiCreateRecord failed\n");
5778 
5779     r = MsiRecordSetInteger(hrec, 1, 1);
5780     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5781     r = MsiRecordSetInteger(hrec, 2, 4);
5782     ok(r == ERROR_SUCCESS, "failed to set integer\n");
5783 
5784     r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5785     ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5786 
5787     r = MsiCloseHandle(hrec);
5788     ok(r == ERROR_SUCCESS, "failed to close record\n");
5789 
5790     r = MsiViewClose(hview);
5791     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5792     r = MsiCloseHandle(hview);
5793     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5794 
5795     query = "SELECT * FROM `table`";
5796     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5797     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5798     r = MsiViewExecute(hview, 0);
5799     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5800     r = MsiViewFetch(hview, &hrec);
5801     ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5802 
5803     r = MsiRecordGetInteger(hrec, 1);
5804     ok(r == 1, "Expected 1, got %d\n", r);
5805     r = MsiRecordGetInteger(hrec, 2);
5806     ok(r == 4, "Expected 4, got %d\n", r);
5807 
5808     r = MsiCloseHandle(hrec);
5809     ok(r == ERROR_SUCCESS, "failed to close record\n");
5810 
5811     r = MsiViewFetch(hview, &hrec);
5812     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5813 
5814     r = MsiViewClose(hview);
5815     ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5816     r = MsiCloseHandle(hview);
5817     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5818 
5819     /* close database */
5820     r = MsiCloseHandle( hdb );
5821     ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5822 }
5823 
5824 static const WCHAR data10[] = { /* MOO */
5825     0x8001, 0x000b,
5826 };
5827 static const WCHAR data11[] = { /* AAR */
5828     0x8002, 0x8005,
5829     0x000c, 0x000f,
5830 };
5831 static const char data12[] = /* _StringData */
5832     "MOOABAARCDonetwofourfive";
5833 static const WCHAR data13[] = { /* _StringPool */
5834 /*  len, refs */
5835     0,   0,    /* string 0 ''     */
5836     0,   0,    /* string 1 ''     */
5837     0,   0,    /* string 2 ''     */
5838     0,   0,    /* string 3 ''     */
5839     0,   0,    /* string 4 ''     */
5840     3,   3,    /* string 5 'MOO'  */
5841     1,   1,    /* string 6 'A'    */
5842     1,   1,    /* string 7 'B'    */
5843     3,   3,    /* string 8 'AAR'  */
5844     1,   1,    /* string 9 'C'    */
5845     1,   1,    /* string a 'D'    */
5846     3,   1,    /* string b 'one'  */
5847     3,   1,    /* string c 'two'  */
5848     0,   0,    /* string d ''     */
5849     4,   1,    /* string e 'four' */
5850     4,   1,    /* string f 'five' */
5851 };
5852 
5853 static void test_stringtable(void)
5854 {
5855     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5856     IStorage *stg = NULL;
5857     IStream *stm;
5858     WCHAR name[0x20];
5859     HRESULT hr;
5860     const char *query;
5861     char buffer[MAX_PATH];
5862     WCHAR data[MAX_PATH];
5863     DWORD sz, read;
5864     UINT r;
5865 
5866     static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5867     static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5868     static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5869     static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5870     static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5871 
5872     DeleteFileA(msifile);
5873 
5874     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5876 
5877     query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5878     r = run_query(hdb, 0, query);
5879     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5880 
5881     query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5882     r = run_query(hdb, 0, query);
5883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5884 
5885     /* insert persistent row */
5886     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5887     r = run_query(hdb, 0, query);
5888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5889 
5890     /* insert persistent row */
5891     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5892     r = run_query(hdb, 0, query);
5893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5894 
5895     /* open a view */
5896     query = "SELECT * FROM `MOO`";
5897     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5899     r = MsiViewExecute(hview, 0);
5900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5901 
5902     hrec = MsiCreateRecord(2);
5903 
5904     r = MsiRecordSetInteger(hrec, 1, 3);
5905     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5906     r = MsiRecordSetStringA(hrec, 2, "three");
5907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5908 
5909     /* insert a nonpersistent row */
5910     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5912 
5913     r = MsiCloseHandle(hrec);
5914     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5915     r = MsiViewClose(hview);
5916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5917     r = MsiCloseHandle(hview);
5918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5919 
5920     /* insert persistent row */
5921     query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5922     r = run_query(hdb, 0, query);
5923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5924 
5925     /* insert persistent row */
5926     query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5927     r = run_query(hdb, 0, query);
5928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5929 
5930     r = MsiDatabaseCommit(hdb);
5931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5932 
5933     r = MsiCloseHandle(hdb);
5934     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5935 
5936     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
5937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5938 
5939     query = "SELECT * FROM `MOO`";
5940     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5942 
5943     r = MsiViewExecute(hview, 0);
5944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5945 
5946     r = MsiViewFetch(hview, &hrec);
5947     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5948 
5949     r = MsiRecordGetFieldCount(hrec);
5950     ok(r == 2, "Expected 2, got %d\n", r);
5951 
5952     r = MsiRecordGetInteger(hrec, 1);
5953     ok(r == 1, "Expected 1, got %d\n", r);
5954 
5955     sz = sizeof(buffer);
5956     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5958     ok(!lstrcmpA(buffer, "one"), "Expected one, got '%s'\n", buffer);
5959 
5960     r = MsiCloseHandle(hrec);
5961     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5962 
5963     r = MsiViewFetch(hview, &hrec);
5964     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5965 
5966     r = MsiViewClose(hview);
5967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5968     r = MsiCloseHandle(hview);
5969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5970     r = MsiCloseHandle(hrec);
5971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5972 
5973     query = "SELECT * FROM `AAR`";
5974     r = MsiDatabaseOpenViewA(hdb, query, &hview);
5975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5976 
5977     r = MsiViewExecute(hview, 0);
5978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5979 
5980     r = MsiViewFetch(hview, &hrec);
5981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5982 
5983     r = MsiRecordGetFieldCount(hrec);
5984     ok(r == 2, "Expected 2, got %d\n", r);
5985 
5986     r = MsiRecordGetInteger(hrec, 1);
5987     ok(r == 2, "Expected 2, got %d\n", r);
5988 
5989     sz = sizeof(buffer);
5990     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5992     ok(!lstrcmpA(buffer, "two"), "Expected two, got '%s'\n", buffer);
5993 
5994     r = MsiCloseHandle(hrec);
5995     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5996 
5997     r = MsiViewFetch(hview, &hrec);
5998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5999 
6000     r = MsiRecordGetFieldCount(hrec);
6001     ok(r == 2, "Expected 2, got %d\n", r);
6002 
6003     r = MsiRecordGetInteger(hrec, 1);
6004     ok(r == 5, "Expected 5, got %d\n", r);
6005 
6006     sz = sizeof(buffer);
6007     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
6008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6009     ok(!lstrcmpA(buffer, "five"), "Expected five, got '%s'\n", buffer);
6010 
6011     r = MsiCloseHandle(hrec);
6012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6013 
6014     r = MsiViewFetch(hview, &hrec);
6015     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6016 
6017     r = MsiViewClose(hview);
6018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6019     r = MsiCloseHandle(hview);
6020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6021     r = MsiCloseHandle(hrec);
6022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6023     r = MsiCloseHandle(hdb);
6024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6025 
6026     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
6027     hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
6028     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6029     ok(stg != NULL, "Expected non-NULL storage\n");
6030 
6031     hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6032     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6033     ok(stm != NULL, "Expected non-NULL stream\n");
6034 
6035     hr = IStream_Read(stm, data, MAX_PATH, &read);
6036     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6037     ok(read == 4, "Expected 4, got %d\n", read);
6038     todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
6039 
6040     hr = IStream_Release(stm);
6041     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6042 
6043     hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6044     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6045     ok(stm != NULL, "Expected non-NULL stream\n");
6046 
6047     hr = IStream_Read(stm, data, MAX_PATH, &read);
6048     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6049     ok(read == 8, "Expected 8, got %d\n", read);
6050     todo_wine
6051     {
6052         ok(!memcmp(data, data11, read), "Unexpected data\n");
6053     }
6054 
6055     hr = IStream_Release(stm);
6056     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6057 
6058     hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6059     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6060     ok(stm != NULL, "Expected non-NULL stream\n");
6061 
6062     hr = IStream_Read(stm, buffer, MAX_PATH, &read);
6063     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6064     ok(read == 24, "Expected 24, got %d\n", read);
6065     ok(!memcmp(buffer, data12, read), "Unexpected data\n");
6066 
6067     hr = IStream_Release(stm);
6068     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6069 
6070     hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6071     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6072     ok(stm != NULL, "Expected non-NULL stream\n");
6073 
6074     hr = IStream_Read(stm, data, MAX_PATH, &read);
6075     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6076     todo_wine
6077     {
6078         ok(read == 64, "Expected 64, got %d\n", read);
6079         ok(!memcmp(data, data13, read), "Unexpected data\n");
6080     }
6081 
6082     hr = IStream_Release(stm);
6083     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6084 
6085     hr = IStorage_Release(stg);
6086     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6087 
6088     DeleteFileA(msifile);
6089 }
6090 
6091 static void test_viewmodify_delete(void)
6092 {
6093     MSIHANDLE hdb = 0, hview = 0, hrec = 0;
6094     UINT r;
6095     const char *query;
6096     char buffer[0x100];
6097     DWORD sz;
6098 
6099     DeleteFileA(msifile);
6100 
6101     /* just MsiOpenDatabase should not create a file */
6102     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6104 
6105     query = "CREATE TABLE `phone` ( "
6106             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
6107             "PRIMARY KEY `id`)";
6108     r = run_query(hdb, 0, query);
6109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6110 
6111     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6112         "VALUES('1', 'Alan', '5030581')";
6113     r = run_query(hdb, 0, query);
6114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6115 
6116     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6117         "VALUES('2', 'Barry', '928440')";
6118     r = run_query(hdb, 0, query);
6119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6120 
6121     query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6122         "VALUES('3', 'Cindy', '2937550')";
6123     r = run_query(hdb, 0, query);
6124     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6125 
6126     query = "SELECT * FROM `phone` WHERE `id` <= 2";
6127     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6129     r = MsiViewExecute(hview, 0);
6130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6131     r = MsiViewFetch(hview, &hrec);
6132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6133 
6134     /* delete 1 */
6135     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6137 
6138     r = MsiCloseHandle(hrec);
6139     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6140     r = MsiViewFetch(hview, &hrec);
6141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6142 
6143     /* delete 2 */
6144     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6146 
6147     r = MsiCloseHandle(hrec);
6148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6149     r = MsiViewClose(hview);
6150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6151     r = MsiCloseHandle(hview);
6152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6153 
6154     query = "SELECT * FROM `phone`";
6155     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6157     r = MsiViewExecute(hview, 0);
6158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6159     r = MsiViewFetch(hview, &hrec);
6160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6161 
6162     r = MsiRecordGetInteger(hrec, 1);
6163     ok(r == 3, "Expected 3, got %d\n", r);
6164 
6165     sz = sizeof(buffer);
6166     r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
6167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6168     ok(!lstrcmpA(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
6169 
6170     sz = sizeof(buffer);
6171     r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
6172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6173     ok(!lstrcmpA(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
6174 
6175     r = MsiCloseHandle(hrec);
6176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6177 
6178     r = MsiViewFetch(hview, &hrec);
6179     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6180 
6181     r = MsiViewClose(hview);
6182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6183     r = MsiCloseHandle(hview);
6184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6185     r = MsiCloseHandle(hdb);
6186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6187 }
6188 
6189 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
6190 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
6191 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
6192 
6193 static const WCHAR data14[] = { /* _StringPool */
6194 /*  len, refs */
6195     0,   0,    /* string 0 ''    */
6196 };
6197 
6198 static const struct {
6199     LPCWSTR name;
6200     const void *data;
6201     DWORD size;
6202 } database_table_data[] =
6203 {
6204     {_Tables, NULL, 0},
6205     {_StringData, NULL, 0},
6206     {_StringPool, data14, sizeof data14},
6207 };
6208 
6209 static void enum_stream_names(IStorage *stg)
6210 {
6211     IEnumSTATSTG *stgenum = NULL;
6212     IStream *stm;
6213     HRESULT hr;
6214     STATSTG stat;
6215     ULONG n, count;
6216     BYTE data[MAX_PATH];
6217     BYTE check[MAX_PATH];
6218     DWORD sz;
6219 
6220     memset(check, 'a', MAX_PATH);
6221 
6222     hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
6223     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6224 
6225     n = 0;
6226     while(TRUE)
6227     {
6228         count = 0;
6229         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
6230         if(FAILED(hr) || !count)
6231             break;
6232 
6233         ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
6234            "Expected table %d name to match\n", n);
6235 
6236         stm = NULL;
6237         hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
6238                                  STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6239         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6240         ok(stm != NULL, "Expected non-NULL stream\n");
6241 
6242         CoTaskMemFree(stat.pwcsName);
6243 
6244         sz = MAX_PATH;
6245         memset(data, 'a', MAX_PATH);
6246         hr = IStream_Read(stm, data, sz, &count);
6247         ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6248 
6249         ok(count == database_table_data[n].size,
6250            "Expected %d, got %d\n", database_table_data[n].size, count);
6251 
6252         if (!database_table_data[n].size)
6253             ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
6254         else
6255             ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
6256                "Expected table %d data to match\n", n);
6257 
6258         IStream_Release(stm);
6259         n++;
6260     }
6261 
6262     ok(n == 3, "Expected 3, got %d\n", n);
6263 
6264     IEnumSTATSTG_Release(stgenum);
6265 }
6266 
6267 static void test_defaultdatabase(void)
6268 {
6269     UINT r;
6270     HRESULT hr;
6271     MSIHANDLE hdb;
6272     IStorage *stg = NULL;
6273 
6274     DeleteFileA(msifile);
6275 
6276     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6278 
6279     r = MsiDatabaseCommit(hdb);
6280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6281 
6282     MsiCloseHandle(hdb);
6283 
6284     hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6285     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6286     ok(stg != NULL, "Expected non-NULL stg\n");
6287 
6288     enum_stream_names(stg);
6289 
6290     IStorage_Release(stg);
6291     DeleteFileA(msifile);
6292 }
6293 
6294 static void test_order(void)
6295 {
6296     MSIHANDLE hdb, hview, hrec;
6297     CHAR buffer[MAX_PATH];
6298     LPCSTR query;
6299     UINT r, sz;
6300     int val;
6301 
6302     hdb = create_db();
6303     ok(hdb, "failed to create db\n");
6304 
6305     query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6306     r = run_query(hdb, 0, query);
6307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6308 
6309     query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6310     r = run_query(hdb, 0, query);
6311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6312 
6313     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6314     r = run_query(hdb, 0, query);
6315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6316 
6317     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6318     r = run_query(hdb, 0, query);
6319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6320 
6321     query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6322     r = run_query(hdb, 0, query);
6323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6324 
6325     query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6326     r = run_query(hdb, 0, query);
6327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6328 
6329     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6330     r = run_query(hdb, 0, query);
6331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6332 
6333     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6334     r = run_query(hdb, 0, query);
6335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6336 
6337     query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6338     r = run_query(hdb, 0, query);
6339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6340 
6341     query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6342     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6344     r = MsiViewExecute(hview, 0);
6345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6346 
6347     r = MsiViewFetch(hview, &hrec);
6348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6349 
6350     val = MsiRecordGetInteger(hrec, 1);
6351     ok(val == 3, "Expected 3, got %d\n", val);
6352 
6353     val = MsiRecordGetInteger(hrec, 2);
6354     ok(val == 4, "Expected 3, got %d\n", val);
6355 
6356     MsiCloseHandle(hrec);
6357 
6358     r = MsiViewFetch(hview, &hrec);
6359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6360 
6361     val = MsiRecordGetInteger(hrec, 1);
6362     ok(val == 5, "Expected 5, got %d\n", val);
6363 
6364     val = MsiRecordGetInteger(hrec, 2);
6365     ok(val == 6, "Expected 6, got %d\n", val);
6366 
6367     MsiCloseHandle(hrec);
6368 
6369     r = MsiViewFetch(hview, &hrec);
6370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6371 
6372     val = MsiRecordGetInteger(hrec, 1);
6373     ok(val == 1, "Expected 1, got %d\n", val);
6374 
6375     val = MsiRecordGetInteger(hrec, 2);
6376     ok(val == 2, "Expected 2, got %d\n", val);
6377 
6378     MsiCloseHandle(hrec);
6379 
6380     r = MsiViewFetch(hview, &hrec);
6381     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6382 
6383     MsiViewClose(hview);
6384     MsiCloseHandle(hview);
6385 
6386     query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6387     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6389     r = MsiViewExecute(hview, 0);
6390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6391 
6392     r = MsiViewFetch(hview, &hrec);
6393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6394 
6395     val = MsiRecordGetInteger(hrec, 1);
6396     ok(val == 1, "Expected 1, got %d\n", val);
6397 
6398     val = MsiRecordGetInteger(hrec, 2);
6399     ok(val == 12, "Expected 12, got %d\n", val);
6400 
6401     MsiCloseHandle(hrec);
6402 
6403     r = MsiViewFetch(hview, &hrec);
6404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6405 
6406     val = MsiRecordGetInteger(hrec, 1);
6407     ok(val == 3, "Expected 3, got %d\n", val);
6408 
6409     val = MsiRecordGetInteger(hrec, 2);
6410     ok(val == 12, "Expected 12, got %d\n", val);
6411 
6412     MsiCloseHandle(hrec);
6413 
6414     r = MsiViewFetch(hview, &hrec);
6415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6416 
6417     val = MsiRecordGetInteger(hrec, 1);
6418     ok(val == 5, "Expected 5, got %d\n", val);
6419 
6420     val = MsiRecordGetInteger(hrec, 2);
6421     ok(val == 12, "Expected 12, got %d\n", val);
6422 
6423     MsiCloseHandle(hrec);
6424 
6425     r = MsiViewFetch(hview, &hrec);
6426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6427 
6428     val = MsiRecordGetInteger(hrec, 1);
6429     ok(val == 1, "Expected 1, got %d\n", val);
6430 
6431     val = MsiRecordGetInteger(hrec, 2);
6432     ok(val == 14, "Expected 14, got %d\n", val);
6433 
6434     MsiCloseHandle(hrec);
6435 
6436     r = MsiViewFetch(hview, &hrec);
6437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6438 
6439     val = MsiRecordGetInteger(hrec, 1);
6440     ok(val == 3, "Expected 3, got %d\n", val);
6441 
6442     val = MsiRecordGetInteger(hrec, 2);
6443     ok(val == 14, "Expected 14, got %d\n", val);
6444 
6445     MsiCloseHandle(hrec);
6446 
6447     r = MsiViewFetch(hview, &hrec);
6448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6449 
6450     val = MsiRecordGetInteger(hrec, 1);
6451     ok(val == 5, "Expected 5, got %d\n", val);
6452 
6453     val = MsiRecordGetInteger(hrec, 2);
6454     ok(val == 14, "Expected 14, got %d\n", val);
6455 
6456     MsiCloseHandle(hrec);
6457 
6458     r = MsiViewFetch(hview, &hrec);
6459     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6460 
6461     val = MsiRecordGetInteger(hrec, 1);
6462     ok(val == 1, "Expected 1, got %d\n", val);
6463 
6464     val = MsiRecordGetInteger(hrec, 2);
6465     ok(val == 10, "Expected 10, got %d\n", val);
6466 
6467     MsiCloseHandle(hrec);
6468 
6469     r = MsiViewFetch(hview, &hrec);
6470     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6471 
6472     val = MsiRecordGetInteger(hrec, 1);
6473     ok(val == 3, "Expected 3, got %d\n", val);
6474 
6475     val = MsiRecordGetInteger(hrec, 2);
6476     ok(val == 10, "Expected 10, got %d\n", val);
6477 
6478     MsiCloseHandle(hrec);
6479 
6480     r = MsiViewFetch(hview, &hrec);
6481     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6482 
6483     val = MsiRecordGetInteger(hrec, 1);
6484     ok(val == 5, "Expected 5, got %d\n", val);
6485 
6486     val = MsiRecordGetInteger(hrec, 2);
6487     ok(val == 10, "Expected 10, got %d\n", val);
6488 
6489     MsiCloseHandle(hrec);
6490 
6491     r = MsiViewFetch(hview, &hrec);
6492     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6493 
6494     MsiViewClose(hview);
6495     MsiCloseHandle(hview);
6496 
6497     query = "SELECT * FROM `Empty` ORDER BY `A`";
6498     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6500     r = MsiViewExecute(hview, 0);
6501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6502 
6503     r = MsiViewFetch(hview, &hrec);
6504     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6505 
6506     MsiViewClose(hview);
6507     MsiCloseHandle(hview);
6508 
6509     query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6510     r = run_query(hdb, 0, query);
6511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6512 
6513     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno',  2)";
6514     r = run_query(hdb, 0, query);
6515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6516 
6517     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos',  3)";
6518     r = run_query(hdb, 0, query);
6519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6520 
6521     query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres',  1)";
6522     r = run_query(hdb, 0, query);
6523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6524 
6525     query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6526     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6528     r = MsiViewExecute(hview, 0);
6529     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6530 
6531     r = MsiViewFetch(hview, &hrec);
6532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6533 
6534     sz = sizeof(buffer);
6535     r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
6536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6537     ok(!lstrcmpA(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6538 
6539     r = MsiRecordGetInteger(hrec, 2);
6540     ok(r == 3, "Expected 3, got %d\n", r);
6541 
6542     MsiCloseHandle(hrec);
6543 
6544     r = MsiViewFetch(hview, &hrec);
6545     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6546 
6547     MsiViewClose(hview);
6548     MsiCloseHandle(hview);
6549     MsiCloseHandle(hdb);
6550 }
6551 
6552 static void test_viewmodify_delete_temporary(void)
6553 {
6554     MSIHANDLE hdb, hview, hrec;
6555     const char *query;
6556     UINT r;
6557 
6558     DeleteFileA(msifile);
6559 
6560     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6562 
6563     query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6564     r = run_query(hdb, 0, query);
6565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6566 
6567     query = "SELECT * FROM `Table`";
6568     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6569     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6570     r = MsiViewExecute(hview, 0);
6571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6572 
6573     hrec = MsiCreateRecord(1);
6574     MsiRecordSetInteger(hrec, 1, 1);
6575 
6576     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6577     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6578 
6579     MsiCloseHandle(hrec);
6580 
6581     hrec = MsiCreateRecord(1);
6582     MsiRecordSetInteger(hrec, 1, 2);
6583 
6584     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6585     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6586 
6587     MsiCloseHandle(hrec);
6588 
6589     hrec = MsiCreateRecord(1);
6590     MsiRecordSetInteger(hrec, 1, 3);
6591 
6592     r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6594 
6595     MsiCloseHandle(hrec);
6596 
6597     hrec = MsiCreateRecord(1);
6598     MsiRecordSetInteger(hrec, 1, 4);
6599 
6600     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6602 
6603     MsiCloseHandle(hrec);
6604     MsiViewClose(hview);
6605     MsiCloseHandle(hview);
6606 
6607     query = "SELECT * FROM `Table` WHERE  `A` = 2";
6608     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6610     r = MsiViewExecute(hview, 0);
6611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6612     r = MsiViewFetch(hview, &hrec);
6613     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6614 
6615     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6617 
6618     MsiCloseHandle(hrec);
6619     MsiViewClose(hview);
6620     MsiCloseHandle(hview);
6621 
6622     query = "SELECT * FROM `Table` WHERE  `A` = 3";
6623     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6624     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6625     r = MsiViewExecute(hview, 0);
6626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6627     r = MsiViewFetch(hview, &hrec);
6628     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6629 
6630     r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6632 
6633     MsiCloseHandle(hrec);
6634     MsiViewClose(hview);
6635     MsiCloseHandle(hview);
6636 
6637     query = "SELECT * FROM `Table` ORDER BY `A`";
6638     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6640     r = MsiViewExecute(hview, 0);
6641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6642 
6643     r = MsiViewFetch(hview, &hrec);
6644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6645 
6646     r = MsiRecordGetInteger(hrec, 1);
6647     ok(r == 1, "Expected 1, got %d\n", r);
6648 
6649     MsiCloseHandle(hrec);
6650 
6651     r = MsiViewFetch(hview, &hrec);
6652     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6653 
6654     r = MsiRecordGetInteger(hrec, 1);
6655     ok(r == 4, "Expected 4, got %d\n", r);
6656 
6657     MsiCloseHandle(hrec);
6658 
6659     r = MsiViewFetch(hview, &hrec);
6660     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6661 
6662     MsiViewClose(hview);
6663     MsiCloseHandle(hview);
6664     MsiCloseHandle(hdb);
6665     DeleteFileA(msifile);
6666 }
6667 
6668 static void test_deleterow(void)
6669 {
6670     MSIHANDLE hdb, hview, hrec;
6671     const char *query;
6672     char buf[MAX_PATH];
6673     UINT r;
6674     DWORD size;
6675 
6676     DeleteFileA(msifile);
6677 
6678     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6680 
6681     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6682     r = run_query(hdb, 0, query);
6683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6684 
6685     query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6686     r = run_query(hdb, 0, query);
6687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6688 
6689     query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6690     r = run_query(hdb, 0, query);
6691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6692 
6693     query = "DELETE FROM `Table` WHERE `A` = 'one'";
6694     r = run_query(hdb, 0, query);
6695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6696 
6697     r = MsiDatabaseCommit(hdb);
6698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6699 
6700     MsiCloseHandle(hdb);
6701 
6702     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
6703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6704 
6705     query = "SELECT * FROM `Table`";
6706     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6708     r = MsiViewExecute(hview, 0);
6709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6710 
6711     r = MsiViewFetch(hview, &hrec);
6712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6713 
6714     size = MAX_PATH;
6715     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6716     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6717     ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6718 
6719     MsiCloseHandle(hrec);
6720 
6721     r = MsiViewFetch(hview, &hrec);
6722     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6723 
6724     MsiViewClose(hview);
6725     MsiCloseHandle(hview);
6726     MsiCloseHandle(hdb);
6727     DeleteFileA(msifile);
6728 }
6729 
6730 static const CHAR import_dat[] = "A\n"
6731                                  "s72\n"
6732                                  "Table\tA\n"
6733                                  "This is a new 'string' ok\n";
6734 
6735 static void test_quotes(void)
6736 {
6737     MSIHANDLE hdb, hview, hrec;
6738     const char *query;
6739     char buf[MAX_PATH];
6740     UINT r;
6741     DWORD size;
6742 
6743     DeleteFileA(msifile);
6744 
6745     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6747 
6748     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6749     r = run_query(hdb, 0, query);
6750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6751 
6752     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6753     r = run_query(hdb, 0, query);
6754     ok(r == ERROR_BAD_QUERY_SYNTAX,
6755        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6756 
6757     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6758     r = run_query(hdb, 0, query);
6759     ok(r == ERROR_BAD_QUERY_SYNTAX,
6760        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6761 
6762     query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6763     r = run_query(hdb, 0, query);
6764     ok(r == ERROR_BAD_QUERY_SYNTAX,
6765        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6766 
6767     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6768     r = run_query(hdb, 0, query);
6769     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6770 
6771     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6772     r = run_query(hdb, 0, query);
6773     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6774 
6775     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6776     r = run_query(hdb, 0, query);
6777     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6778 
6779     query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6780     r = run_query(hdb, 0, query);
6781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6782 
6783     query = "SELECT * FROM `Table`";
6784     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6786 
6787     r = MsiViewExecute(hview, 0);
6788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6789 
6790     r = MsiViewFetch(hview, &hrec);
6791     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6792 
6793     size = MAX_PATH;
6794     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6795     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6796     ok(!lstrcmpA(buf, "This is a \"string\" ok"),
6797        "Expected \"This is a \"string\" ok\", got %s\n", buf);
6798 
6799     MsiCloseHandle(hrec);
6800 
6801     r = MsiViewFetch(hview, &hrec);
6802     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6803 
6804     MsiViewClose(hview);
6805     MsiCloseHandle(hview);
6806 
6807     write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6808 
6809     r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6810     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6811 
6812     DeleteFileA("import.idt");
6813 
6814     query = "SELECT * FROM `Table`";
6815     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6817 
6818     r = MsiViewExecute(hview, 0);
6819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6820 
6821     r = MsiViewFetch(hview, &hrec);
6822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6823 
6824     size = MAX_PATH;
6825     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6827     ok(!lstrcmpA(buf, "This is a new 'string' ok"),
6828        "Expected \"This is a new 'string' ok\", got %s\n", buf);
6829 
6830     MsiCloseHandle(hrec);
6831 
6832     r = MsiViewFetch(hview, &hrec);
6833     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6834 
6835     MsiViewClose(hview);
6836     MsiCloseHandle(hview);
6837     MsiCloseHandle(hdb);
6838     DeleteFileA(msifile);
6839 }
6840 
6841 static void test_carriagereturn(void)
6842 {
6843     MSIHANDLE hdb, hview, hrec;
6844     const char *query;
6845     char buf[MAX_PATH];
6846     UINT r;
6847     DWORD size;
6848 
6849     DeleteFileA(msifile);
6850 
6851     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6853 
6854     query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6855     r = run_query(hdb, 0, query);
6856     ok(r == ERROR_BAD_QUERY_SYNTAX,
6857        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6858 
6859     query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6860     r = run_query(hdb, 0, query);
6861     ok(r == ERROR_BAD_QUERY_SYNTAX,
6862        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6863 
6864     query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6865     r = run_query(hdb, 0, query);
6866     ok(r == ERROR_BAD_QUERY_SYNTAX,
6867        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6868 
6869     query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6870     r = run_query(hdb, 0, query);
6871     ok(r == ERROR_BAD_QUERY_SYNTAX,
6872        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6873 
6874     query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6875     r = run_query(hdb, 0, query);
6876     ok(r == ERROR_BAD_QUERY_SYNTAX,
6877        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6878 
6879     query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6880     r = run_query(hdb, 0, query);
6881     ok(r == ERROR_BAD_QUERY_SYNTAX,
6882        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6883 
6884     query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6885     r = run_query(hdb, 0, query);
6886     ok(r == ERROR_BAD_QUERY_SYNTAX,
6887        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6888 
6889     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6890     r = run_query(hdb, 0, query);
6891     ok(r == ERROR_BAD_QUERY_SYNTAX,
6892        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6893 
6894     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6895     r = run_query(hdb, 0, query);
6896     ok(r == ERROR_BAD_QUERY_SYNTAX,
6897        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6898 
6899     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6900     r = run_query(hdb, 0, query);
6901     ok(r == ERROR_BAD_QUERY_SYNTAX,
6902        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6903 
6904     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6905     r = run_query(hdb, 0, query);
6906     ok(r == ERROR_BAD_QUERY_SYNTAX,
6907        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6908 
6909     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6910     r = run_query(hdb, 0, query);
6911     ok(r == ERROR_BAD_QUERY_SYNTAX,
6912        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6913 
6914     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6915     r = run_query(hdb, 0, query);
6916     ok(r == ERROR_BAD_QUERY_SYNTAX,
6917        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6918 
6919     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6920     r = run_query(hdb, 0, query);
6921     ok(r == ERROR_BAD_QUERY_SYNTAX,
6922        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6923 
6924     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6925     r = run_query(hdb, 0, query);
6926     ok(r == ERROR_BAD_QUERY_SYNTAX,
6927        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6928 
6929     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6930     r = run_query(hdb, 0, query);
6931     ok(r == ERROR_BAD_QUERY_SYNTAX,
6932        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6933 
6934     query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6935     r = run_query(hdb, 0, query);
6936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6937 
6938     query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6939     r = run_query(hdb, 0, query);
6940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6941 
6942     query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6943     r = run_query(hdb, 0, query);
6944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6945 
6946     query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6947     r = run_query(hdb, 0, query);
6948     ok(r == ERROR_BAD_QUERY_SYNTAX,
6949        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6950 
6951     query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6952     r = run_query(hdb, 0, query);
6953     ok(r == ERROR_BAD_QUERY_SYNTAX,
6954        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6955 
6956     query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6957     r = run_query(hdb, 0, query);
6958     ok(r == ERROR_BAD_QUERY_SYNTAX,
6959        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6960 
6961     query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6962     r = run_query(hdb, 0, query);
6963     ok(r == ERROR_BAD_QUERY_SYNTAX,
6964        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6965 
6966     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6967     r = run_query(hdb, 0, query);
6968     ok(r == ERROR_BAD_QUERY_SYNTAX,
6969        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6970 
6971     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6972     r = run_query(hdb, 0, query);
6973     ok(r == ERROR_BAD_QUERY_SYNTAX,
6974        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6975 
6976     query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6977     r = run_query(hdb, 0, query);
6978     ok(r == ERROR_BAD_QUERY_SYNTAX,
6979        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6980 
6981     query = "SELECT * FROM `_Tables`";
6982     r = MsiDatabaseOpenViewA(hdb, query, &hview);
6983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6984     r = MsiViewExecute(hview, 0);
6985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6986 
6987     r = MsiViewFetch(hview, &hrec);
6988     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6989 
6990     size = MAX_PATH;
6991     r = MsiRecordGetStringA(hrec, 1, buf, &size);
6992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6993     ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6994 
6995     MsiCloseHandle(hrec);
6996 
6997     r = MsiViewFetch(hview, &hrec);
6998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6999 
7000     size = MAX_PATH;
7001     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7003     ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
7004 
7005     MsiCloseHandle(hrec);
7006 
7007     r = MsiViewFetch(hview, &hrec);
7008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7009 
7010     size = MAX_PATH;
7011     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7013     ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
7014 
7015     MsiCloseHandle(hrec);
7016 
7017     r = MsiViewFetch(hview, &hrec);
7018     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7019 
7020     MsiViewClose(hview);
7021     MsiCloseHandle(hview);
7022 
7023     MsiCloseHandle(hdb);
7024     DeleteFileA(msifile);
7025 }
7026 
7027 static void test_noquotes(void)
7028 {
7029     MSIHANDLE hdb, hview, hrec;
7030     const char *query;
7031     char buf[MAX_PATH];
7032     UINT r;
7033     DWORD size;
7034 
7035     DeleteFileA(msifile);
7036 
7037     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7039 
7040     query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7041     r = run_query(hdb, 0, query);
7042     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7043 
7044     query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
7045     r = run_query(hdb, 0, query);
7046     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7047 
7048     query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
7049     r = run_query(hdb, 0, query);
7050     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7051 
7052     query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
7053     r = run_query(hdb, 0, query);
7054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7055 
7056     query = "SELECT * FROM `_Tables`";
7057     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7059     r = MsiViewExecute(hview, 0);
7060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7061 
7062     r = MsiViewFetch(hview, &hrec);
7063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7064 
7065     size = MAX_PATH;
7066     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7068     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
7069 
7070     MsiCloseHandle(hrec);
7071 
7072     r = MsiViewFetch(hview, &hrec);
7073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7074 
7075     size = MAX_PATH;
7076     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7078     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
7079 
7080     MsiCloseHandle(hrec);
7081 
7082     r = MsiViewFetch(hview, &hrec);
7083     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7084 
7085     size = MAX_PATH;
7086     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7088     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7089 
7090     MsiCloseHandle(hrec);
7091 
7092     r = MsiViewFetch(hview, &hrec);
7093     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7094 
7095     MsiViewClose(hview);
7096     MsiCloseHandle(hview);
7097 
7098     query = "SELECT * FROM `_Columns`";
7099     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7101     r = MsiViewExecute(hview, 0);
7102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7103 
7104     r = MsiViewFetch(hview, &hrec);
7105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7106 
7107     size = MAX_PATH;
7108     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7110     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
7111 
7112     r = MsiRecordGetInteger(hrec, 2);
7113     ok(r == 1, "Expected 1, got %d\n", r);
7114 
7115     size = MAX_PATH;
7116     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7118     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7119 
7120     MsiCloseHandle(hrec);
7121 
7122     r = MsiViewFetch(hview, &hrec);
7123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7124 
7125     size = MAX_PATH;
7126     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7128     ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
7129 
7130     r = MsiRecordGetInteger(hrec, 2);
7131     ok(r == 1, "Expected 1, got %d\n", r);
7132 
7133     size = MAX_PATH;
7134     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7136     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7137 
7138     MsiCloseHandle(hrec);
7139 
7140     r = MsiViewFetch(hview, &hrec);
7141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7142 
7143     size = MAX_PATH;
7144     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7146     ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7147 
7148     r = MsiRecordGetInteger(hrec, 2);
7149     ok(r == 1, "Expected 1, got %d\n", r);
7150 
7151     size = MAX_PATH;
7152     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7154     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7155 
7156     MsiCloseHandle(hrec);
7157 
7158     r = MsiViewFetch(hview, &hrec);
7159     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7160 
7161     MsiViewClose(hview);
7162     MsiCloseHandle(hview);
7163 
7164     query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
7165     r = run_query(hdb, 0, query);
7166     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7167 
7168     query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
7169     r = run_query(hdb, 0, query);
7170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7171 
7172     query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
7173     r = run_query(hdb, 0, query);
7174     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7175 
7176     query = "SELECT * FROM Table WHERE `A` = 'hi'";
7177     r = run_query(hdb, 0, query);
7178     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7179 
7180     query = "SELECT * FROM `Table` WHERE `A` = hi";
7181     r = run_query(hdb, 0, query);
7182     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7183 
7184     query = "SELECT * FROM Table";
7185     r = run_query(hdb, 0, query);
7186     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7187 
7188     query = "SELECT * FROM Table2";
7189     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7191     r = MsiViewExecute(hview, 0);
7192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7193 
7194     r = MsiViewFetch(hview, &hrec);
7195     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7196 
7197     MsiViewClose(hview);
7198     MsiCloseHandle(hview);
7199 
7200     query = "SELECT * FROM `Table` WHERE A = 'hi'";
7201     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7203     r = MsiViewExecute(hview, 0);
7204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7205 
7206     r = MsiViewFetch(hview, &hrec);
7207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7208 
7209     size = MAX_PATH;
7210     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7212     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7213 
7214     MsiCloseHandle(hrec);
7215 
7216     r = MsiViewFetch(hview, &hrec);
7217     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7218 
7219     MsiViewClose(hview);
7220     MsiCloseHandle(hview);
7221     MsiCloseHandle(hdb);
7222     DeleteFileA(msifile);
7223 }
7224 
7225 static void read_file_data(LPCSTR filename, LPSTR buffer)
7226 {
7227     HANDLE file;
7228     DWORD read;
7229 
7230     file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
7231     ZeroMemory(buffer, MAX_PATH);
7232     ReadFile(file, buffer, MAX_PATH, &read, NULL);
7233     CloseHandle(file);
7234 }
7235 
7236 static void test_forcecodepage(void)
7237 {
7238     MSIHANDLE hdb;
7239     const char *query;
7240     char buffer[MAX_PATH];
7241     UINT r;
7242 
7243     DeleteFileA(msifile);
7244     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
7245 
7246     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7248 
7249     query = "SELECT * FROM `_ForceCodepage`";
7250     r = run_query(hdb, 0, query);
7251     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7252 
7253     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7254     r = run_query(hdb, 0, query);
7255     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7256 
7257     query = "SELECT * FROM `_ForceCodepage`";
7258     r = run_query(hdb, 0, query);
7259     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7260 
7261     r = MsiDatabaseCommit(hdb);
7262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263 
7264     query = "SELECT * FROM `_ForceCodepage`";
7265     r = run_query(hdb, 0, query);
7266     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7267 
7268     MsiCloseHandle(hdb);
7269 
7270     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7272 
7273     query = "SELECT * FROM `_ForceCodepage`";
7274     r = run_query(hdb, 0, query);
7275     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7276 
7277     r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7279 
7280     read_file_data("forcecodepage.idt", buffer);
7281     ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7282        "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7283 
7284     create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7285 
7286     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7288 
7289     r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7291 
7292     read_file_data("forcecodepage.idt", buffer);
7293     ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
7294        "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7295 
7296     create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
7297 
7298     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7299     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7300 
7301     MsiCloseHandle(hdb);
7302     DeleteFileA(msifile);
7303     DeleteFileA("forcecodepage.idt");
7304 }
7305 
7306 static void test_viewmodify_refresh(void)
7307 {
7308     MSIHANDLE hdb, hview, hrec;
7309     const char *query;
7310     char buffer[MAX_PATH];
7311     UINT r;
7312     DWORD size;
7313 
7314     DeleteFileA(msifile);
7315 
7316     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7318 
7319     query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7320     r = run_query(hdb, 0, query);
7321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7322 
7323     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7324     r = run_query(hdb, 0, query);
7325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7326 
7327     query = "SELECT * FROM `Table`";
7328     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7330     r = MsiViewExecute(hview, 0);
7331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7332 
7333     r = MsiViewFetch(hview, &hrec);
7334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7335 
7336     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7337     r = run_query(hdb, 0, query);
7338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7339 
7340     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7342 
7343     size = MAX_PATH;
7344     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7346     ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7347     ok(size == 2, "Expected 2, got %d\n", size);
7348 
7349     r = MsiRecordGetInteger(hrec, 2);
7350     ok(r == 2, "Expected 2, got %d\n", r);
7351 
7352     MsiCloseHandle(hrec);
7353     MsiViewClose(hview);
7354     MsiCloseHandle(hview);
7355 
7356     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7357     r = run_query(hdb, 0, query);
7358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7359 
7360     query = "SELECT * FROM `Table` WHERE `B` = 3";
7361     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7363     r = MsiViewExecute(hview, 0);
7364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7365 
7366     r = MsiViewFetch(hview, &hrec);
7367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7368 
7369     query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7370     r = run_query(hdb, 0, query);
7371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7372 
7373     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7374     r = run_query(hdb, 0, query);
7375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7376 
7377     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7379 
7380     size = MAX_PATH;
7381     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7383     ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7384     ok(size == 5, "Expected 5, got %d\n", size);
7385 
7386     r = MsiRecordGetInteger(hrec, 2);
7387     ok(r == 2, "Expected 2, got %d\n", r);
7388 
7389     MsiCloseHandle(hrec);
7390     MsiViewClose(hview);
7391     MsiCloseHandle(hview);
7392     MsiCloseHandle(hdb);
7393     DeleteFileA(msifile);
7394 }
7395 
7396 static void test_where_viewmodify(void)
7397 {
7398     MSIHANDLE hdb, hview, hrec;
7399     const char *query;
7400     UINT r;
7401 
7402     DeleteFileA(msifile);
7403 
7404     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7406 
7407     query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7408     r = run_query(hdb, 0, query);
7409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7410 
7411     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7412     r = run_query(hdb, 0, query);
7413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7414 
7415     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7416     r = run_query(hdb, 0, query);
7417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7418 
7419     query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7420     r = run_query(hdb, 0, query);
7421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7422 
7423     /* `B` = 3 doesn't match, but the view shouldn't be executed */
7424     query = "SELECT * FROM `Table` WHERE `B` = 3";
7425     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7427 
7428     hrec = MsiCreateRecord(2);
7429     MsiRecordSetInteger(hrec, 1, 7);
7430     MsiRecordSetInteger(hrec, 2, 8);
7431 
7432     r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7434 
7435     MsiCloseHandle(hrec);
7436     MsiViewClose(hview);
7437     MsiCloseHandle(hview);
7438 
7439     query = "SELECT * FROM `Table` WHERE `A` = 7";
7440     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7442     r = MsiViewExecute(hview, 0);
7443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7444 
7445     r = MsiViewFetch(hview, &hrec);
7446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7447 
7448     r = MsiRecordGetInteger(hrec, 1);
7449     ok(r == 7, "Expected 7, got %d\n", r);
7450 
7451     r = MsiRecordGetInteger(hrec, 2);
7452     ok(r == 8, "Expected 8, got %d\n", r);
7453 
7454     MsiRecordSetInteger(hrec, 2, 9);
7455 
7456     r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7458 
7459     MsiCloseHandle(hrec);
7460     MsiViewClose(hview);
7461     MsiCloseHandle(hview);
7462 
7463     query = "SELECT * FROM `Table` WHERE `A` = 7";
7464     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7466     r = MsiViewExecute(hview, 0);
7467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7468 
7469     r = MsiViewFetch(hview, &hrec);
7470     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7471 
7472     r = MsiRecordGetInteger(hrec, 1);
7473     ok(r == 7, "Expected 7, got %d\n", r);
7474 
7475     r = MsiRecordGetInteger(hrec, 2);
7476     ok(r == 9, "Expected 9, got %d\n", r);
7477 
7478     query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7479     r = run_query(hdb, 0, query);
7480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7481 
7482     r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7484 
7485     r = MsiRecordGetInteger(hrec, 1);
7486     ok(r == 7, "Expected 7, got %d\n", r);
7487 
7488     r = MsiRecordGetInteger(hrec, 2);
7489     ok(r == 10, "Expected 10, got %d\n", r);
7490 
7491     MsiCloseHandle(hrec);
7492     MsiViewClose(hview);
7493     MsiCloseHandle(hview);
7494     MsiCloseHandle(hdb);
7495 }
7496 
7497 static BOOL create_storage(LPCSTR name)
7498 {
7499     WCHAR nameW[MAX_PATH];
7500     IStorage *stg;
7501     IStream *stm;
7502     HRESULT hr;
7503     DWORD count;
7504     BOOL res = FALSE;
7505 
7506     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7507     hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7508                           STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7509     if (FAILED(hr))
7510         return FALSE;
7511 
7512     hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7513                                0, 0, &stm);
7514     if (FAILED(hr))
7515         goto done;
7516 
7517     hr = IStream_Write(stm, "stgdata", 8, &count);
7518     if (SUCCEEDED(hr))
7519         res = TRUE;
7520 
7521 done:
7522     IStream_Release(stm);
7523     IStorage_Release(stg);
7524 
7525     return res;
7526 }
7527 
7528 static void test_storages_table(void)
7529 {
7530     MSIHANDLE hdb, hview, hrec;
7531     IStorage *stg, *inner;
7532     IStream *stm;
7533     char file[MAX_PATH];
7534     char buf[MAX_PATH];
7535     WCHAR name[MAX_PATH];
7536     LPCSTR query;
7537     HRESULT hr;
7538     DWORD size;
7539     UINT r;
7540 
7541     hdb = create_db();
7542     ok(hdb, "failed to create db\n");
7543 
7544     r = MsiDatabaseCommit(hdb);
7545     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7546 
7547     MsiCloseHandle(hdb);
7548 
7549     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb);
7550     ok(r == ERROR_SUCCESS , "Failed to open database\n");
7551 
7552     /* check the column types */
7553     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7554     ok(hrec, "failed to get column info hrecord\n");
7555     ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7556     ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7557 
7558     MsiCloseHandle(hrec);
7559 
7560     /* now try the names */
7561     hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7562     ok(hrec, "failed to get column info hrecord\n");
7563     ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7564     ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7565 
7566     MsiCloseHandle(hrec);
7567 
7568     create_storage("storage.bin");
7569 
7570     hrec = MsiCreateRecord(2);
7571     MsiRecordSetStringA(hrec, 1, "stgname");
7572 
7573     r = MsiRecordSetStreamA(hrec, 2, "storage.bin");
7574     ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7575 
7576     DeleteFileA("storage.bin");
7577 
7578     query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7579     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7580     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7581 
7582     r = MsiViewExecute(hview, hrec);
7583     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7584 
7585     MsiCloseHandle(hrec);
7586     MsiViewClose(hview);
7587     MsiCloseHandle(hview);
7588 
7589     query = "SELECT `Name`, `Data` FROM `_Storages`";
7590     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7591     ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7592 
7593     r = MsiViewExecute(hview, 0);
7594     ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7595 
7596     r = MsiViewFetch(hview, &hrec);
7597     ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7598 
7599     size = MAX_PATH;
7600     r = MsiRecordGetStringA(hrec, 1, file, &size);
7601     ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7602     ok(!lstrcmpA(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7603 
7604     size = MAX_PATH;
7605     lstrcpyA(buf, "apple");
7606     r = MsiRecordReadStream(hrec, 2, buf, &size);
7607     ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7608     ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7609     ok(size == 0, "Expected 0, got %d\n", size);
7610 
7611     MsiCloseHandle(hrec);
7612 
7613     r = MsiViewFetch(hview, &hrec);
7614     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7615 
7616     MsiViewClose(hview);
7617     MsiCloseHandle(hview);
7618 
7619     MsiDatabaseCommit(hdb);
7620     MsiCloseHandle(hdb);
7621 
7622     MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7623     hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7624                         STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7625     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7626     ok(stg != NULL, "Expected non-NULL storage\n");
7627 
7628     MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7629     hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7630                               NULL, 0, &inner);
7631     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7632     ok(inner != NULL, "Expected non-NULL storage\n");
7633 
7634     MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7635     hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7636     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7637     ok(stm != NULL, "Expected non-NULL stream\n");
7638 
7639     hr = IStream_Read(stm, buf, MAX_PATH, &size);
7640     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7641     ok(size == 8, "Expected 8, got %d\n", size);
7642     ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7643 
7644     IStream_Release(stm);
7645     IStorage_Release(inner);
7646 
7647     IStorage_Release(stg);
7648     DeleteFileA(msifile);
7649 }
7650 
7651 static void test_dbtopackage(void)
7652 {
7653     MSIHANDLE hdb, hpkg;
7654     CHAR package[12], buf[MAX_PATH];
7655     DWORD size;
7656     UINT r;
7657 
7658     /* create an empty database, transact mode */
7659     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7660     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7661 
7662     set_summary_info(hdb);
7663 
7664     r = create_directory_table(hdb);
7665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7666 
7667     r = create_custom_action_table(hdb);
7668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7669 
7670     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7672 
7673     sprintf(package, "#%u", hdb);
7674     r = MsiOpenPackageA(package, &hpkg);
7675     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7676     {
7677         skip("Not enough rights to perform tests\n");
7678         goto error;
7679     }
7680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7681 
7682     /* property is not set yet */
7683     size = MAX_PATH;
7684     lstrcpyA(buf, "kiwi");
7685     r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7687     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7688     ok(size == 0, "Expected 0, got %d\n", size);
7689 
7690     /* run the custom action to set the property */
7691     r = MsiDoActionA(hpkg, "SetProp");
7692     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7693 
7694     /* property is now set */
7695     size = MAX_PATH;
7696     lstrcpyA(buf, "kiwi");
7697     r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7699     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7700     ok(size == 5, "Expected 5, got %d\n", size);
7701 
7702     MsiCloseHandle(hpkg);
7703 
7704     /* reset the package */
7705     r = MsiOpenPackageA(package, &hpkg);
7706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7707 
7708     /* property is not set anymore */
7709     size = MAX_PATH;
7710     lstrcpyA(buf, "kiwi");
7711     r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7713     todo_wine
7714     {
7715         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7716         ok(size == 0, "Expected 0, got %d\n", size);
7717     }
7718 
7719     MsiCloseHandle(hdb);
7720     MsiCloseHandle(hpkg);
7721 
7722     /* create an empty database, direct mode */
7723     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7724     ok(r == ERROR_SUCCESS, "Failed to create database\n");
7725 
7726     set_summary_info(hdb);
7727 
7728     r = create_directory_table(hdb);
7729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7730 
7731     r = create_custom_action_table(hdb);
7732     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7733 
7734     r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7736 
7737     sprintf(package, "#%u", hdb);
7738     r = MsiOpenPackageA(package, &hpkg);
7739     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7740 
7741     /* property is not set yet */
7742     size = MAX_PATH;
7743     lstrcpyA(buf, "kiwi");
7744     r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7746     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7747     ok(size == 0, "Expected 0, got %d\n", size);
7748 
7749     /* run the custom action to set the property */
7750     r = MsiDoActionA(hpkg, "SetProp");
7751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7752 
7753     /* property is now set */
7754     size = MAX_PATH;
7755     lstrcpyA(buf, "kiwi");
7756     r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7758     ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7759     ok(size == 5, "Expected 5, got %d\n", size);
7760 
7761     MsiCloseHandle(hpkg);
7762 
7763     /* reset the package */
7764     r = MsiOpenPackageA(package, &hpkg);
7765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7766 
7767     /* property is not set anymore */
7768     size = MAX_PATH;
7769     lstrcpyA(buf, "kiwi");
7770     r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7772     todo_wine
7773     {
7774         ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7775         ok(size == 0, "Expected 0, got %d\n", size);
7776     }
7777 
7778     MsiCloseHandle(hpkg);
7779 
7780 error:
7781     MsiCloseHandle(hdb);
7782     DeleteFileA(msifile);
7783 }
7784 
7785 static void test_droptable(void)
7786 {
7787     MSIHANDLE hdb, hview, hrec;
7788     CHAR buf[MAX_PATH];
7789     LPCSTR query;
7790     DWORD size;
7791     UINT r;
7792 
7793     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7795 
7796     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7797     r = run_query(hdb, 0, query);
7798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7799 
7800     query = "SELECT * FROM `One`";
7801     r = do_query(hdb, query, &hrec);
7802     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7803 
7804     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7805     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7807     r = MsiViewExecute(hview, 0);
7808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7809 
7810     r = MsiViewFetch(hview, &hrec);
7811     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7812 
7813     size = MAX_PATH;
7814     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7816     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7817 
7818     MsiCloseHandle(hrec);
7819     MsiViewClose(hview);
7820     MsiCloseHandle(hview);
7821 
7822     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7823     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7825     r = MsiViewExecute(hview, 0);
7826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7827 
7828     r = MsiViewFetch(hview, &hrec);
7829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7830 
7831     size = MAX_PATH;
7832     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7834     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7835 
7836     r = MsiRecordGetInteger(hrec, 2);
7837     ok(r == 1, "Expected 1, got %d\n", r);
7838 
7839     size = MAX_PATH;
7840     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7842     ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7843 
7844     MsiCloseHandle(hrec);
7845 
7846     r = MsiViewFetch(hview, &hrec);
7847     ok(r == ERROR_NO_MORE_ITEMS,
7848        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7849 
7850     MsiViewClose(hview);
7851     MsiCloseHandle(hview);
7852 
7853     query = "DROP `One`";
7854     r = run_query(hdb, 0, query);
7855     ok(r == ERROR_BAD_QUERY_SYNTAX,
7856        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7857 
7858     query = "DROP TABLE";
7859     r = run_query(hdb, 0, query);
7860     ok(r == ERROR_BAD_QUERY_SYNTAX,
7861        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7862 
7863     query = "DROP TABLE `One`";
7864     hview = 0;
7865     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7867     r = MsiViewExecute(hview, 0);
7868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7869 
7870     r = MsiViewFetch(hview, &hrec);
7871     ok(r == ERROR_FUNCTION_FAILED,
7872        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7873 
7874     MsiViewClose(hview);
7875     MsiCloseHandle(hview);
7876 
7877     query = "SELECT * FROM `IDontExist`";
7878     r = do_query(hdb, query, &hrec);
7879     ok(r == ERROR_BAD_QUERY_SYNTAX,
7880        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7881 
7882     query = "SELECT * FROM `One`";
7883     r = do_query(hdb, query, &hrec);
7884     ok(r == ERROR_BAD_QUERY_SYNTAX,
7885        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7886 
7887     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7888     r = run_query(hdb, 0, query);
7889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7890 
7891     query = "DROP TABLE One";
7892     r = run_query(hdb, 0, query);
7893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7894 
7895     query = "SELECT * FROM `One`";
7896     r = do_query(hdb, query, &hrec);
7897     ok(r == ERROR_BAD_QUERY_SYNTAX,
7898        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7899 
7900     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7901     r = do_query(hdb, query, &hrec);
7902     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7903 
7904     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7905     r = do_query(hdb, query, &hrec);
7906     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7907 
7908     query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7909     r = run_query(hdb, 0, query);
7910     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7911 
7912     query = "SELECT * FROM `One`";
7913     r = do_query(hdb, query, &hrec);
7914     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7915 
7916     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7917     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7918     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7919     r = MsiViewExecute(hview, 0);
7920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7921 
7922     r = MsiViewFetch(hview, &hrec);
7923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7924 
7925     size = MAX_PATH;
7926     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7927     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7928     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7929 
7930     MsiCloseHandle(hrec);
7931     MsiViewClose(hview);
7932     MsiCloseHandle(hview);
7933 
7934     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7935     r = MsiDatabaseOpenViewA(hdb, query, &hview);
7936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7937     r = MsiViewExecute(hview, 0);
7938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7939 
7940     r = MsiViewFetch(hview, &hrec);
7941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7942 
7943     size = MAX_PATH;
7944     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7946     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7947 
7948     r = MsiRecordGetInteger(hrec, 2);
7949     ok(r == 1, "Expected 1, got %d\n", r);
7950 
7951     size = MAX_PATH;
7952     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7954     ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7955 
7956     MsiCloseHandle(hrec);
7957 
7958     r = MsiViewFetch(hview, &hrec);
7959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7960 
7961     size = MAX_PATH;
7962     r = MsiRecordGetStringA(hrec, 1, buf, &size);
7963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7964     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7965 
7966     r = MsiRecordGetInteger(hrec, 2);
7967     ok(r == 2, "Expected 2, got %d\n", r);
7968 
7969     size = MAX_PATH;
7970     r = MsiRecordGetStringA(hrec, 3, buf, &size);
7971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7972     ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7973 
7974     MsiCloseHandle(hrec);
7975 
7976     r = MsiViewFetch(hview, &hrec);
7977     ok(r == ERROR_NO_MORE_ITEMS,
7978        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7979 
7980     MsiViewClose(hview);
7981     MsiCloseHandle(hview);
7982 
7983     query = "DROP TABLE One";
7984     r = run_query(hdb, 0, query);
7985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7986 
7987     query = "SELECT * FROM `One`";
7988     r = do_query(hdb, query, &hrec);
7989     ok(r == ERROR_BAD_QUERY_SYNTAX,
7990        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7991 
7992     query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7993     r = do_query(hdb, query, &hrec);
7994     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7995 
7996     query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7997     r = do_query(hdb, query, &hrec);
7998     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7999 
8000     MsiCloseHandle(hdb);
8001     DeleteFileA(msifile);
8002 }
8003 
8004 static void test_dbmerge(void)
8005 {
8006     static const WCHAR refdbW[] = {'r','e','f','d','b','.','m','s','i',0};
8007     MSIHANDLE hdb, href, hview, hrec;
8008     CHAR buf[MAX_PATH];
8009     LPCSTR query;
8010     DWORD size;
8011     UINT r;
8012 
8013     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8015 
8016     r = MsiOpenDatabaseW(refdbW, MSIDBOPEN_CREATE, &href);
8017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8018 
8019     /* hDatabase is invalid */
8020     r = MsiDatabaseMergeA(0, href, "MergeErrors");
8021     ok(r == ERROR_INVALID_HANDLE,
8022        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8023 
8024     /* hDatabaseMerge is invalid */
8025     r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
8026     ok(r == ERROR_INVALID_HANDLE,
8027        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8028 
8029     /* szTableName is NULL */
8030     r = MsiDatabaseMergeA(hdb, href, NULL);
8031     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8032 
8033     /* szTableName is empty */
8034     r = MsiDatabaseMergeA(hdb, href, "");
8035     ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
8036 
8037     /* both DBs empty, szTableName is valid */
8038     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8039     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8040 
8041     query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
8042     r = run_query(hdb, 0, query);
8043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8044 
8045     query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
8046     r = run_query(href, 0, query);
8047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8048 
8049     /* column types don't match */
8050     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8051     ok(r == ERROR_DATATYPE_MISMATCH,
8052        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8053 
8054     /* nothing in MergeErrors */
8055     query = "SELECT * FROM `MergeErrors`";
8056     r = do_query(hdb, query, &hrec);
8057     ok(r == ERROR_BAD_QUERY_SYNTAX,
8058        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8059 
8060     query = "DROP TABLE `One`";
8061     r = run_query(hdb, 0, query);
8062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8063 
8064     query = "DROP TABLE `One`";
8065     r = run_query(href, 0, query);
8066     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8067 
8068     query = "CREATE TABLE `One` ( "
8069         "`A` CHAR(72), "
8070         "`B` CHAR(56), "
8071         "`C` CHAR(64) LOCALIZABLE, "
8072         "`D` LONGCHAR, "
8073         "`E` CHAR(72) NOT NULL, "
8074         "`F` CHAR(56) NOT NULL, "
8075         "`G` CHAR(64) NOT NULL LOCALIZABLE, "
8076         "`H` LONGCHAR NOT NULL "
8077         "PRIMARY KEY `A` )";
8078     r = run_query(hdb, 0, query);
8079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8080 
8081     query = "CREATE TABLE `One` ( "
8082         "`A` CHAR(64), "
8083         "`B` CHAR(64), "
8084         "`C` CHAR(64), "
8085         "`D` CHAR(64), "
8086         "`E` CHAR(64) NOT NULL, "
8087         "`F` CHAR(64) NOT NULL, "
8088         "`G` CHAR(64) NOT NULL, "
8089         "`H` CHAR(64) NOT NULL "
8090         "PRIMARY KEY `A` )";
8091     r = run_query(href, 0, query);
8092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8093 
8094     /* column string types don't match exactly */
8095     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8096     ok(r == ERROR_SUCCESS,
8097        "Expected ERROR_SUCCESS, got %d\n", r);
8098 
8099     /* nothing in MergeErrors */
8100     query = "SELECT * FROM `MergeErrors`";
8101     r = do_query(hdb, query, &hrec);
8102     ok(r == ERROR_BAD_QUERY_SYNTAX,
8103        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8104 
8105     query = "DROP TABLE `One`";
8106     r = run_query(hdb, 0, query);
8107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8108 
8109     query = "DROP TABLE `One`";
8110     r = run_query(href, 0, query);
8111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8112 
8113     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8114     r = run_query(hdb, 0, query);
8115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8116 
8117     query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
8118     r = run_query(href, 0, query);
8119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8120 
8121     /* column names don't match */
8122     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8123     ok(r == ERROR_DATATYPE_MISMATCH,
8124        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8125 
8126     /* nothing in MergeErrors */
8127     query = "SELECT * FROM `MergeErrors`";
8128     r = do_query(hdb, query, &hrec);
8129     ok(r == ERROR_BAD_QUERY_SYNTAX,
8130        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8131 
8132     query = "DROP TABLE `One`";
8133     r = run_query(hdb, 0, query);
8134     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8135 
8136     query = "DROP TABLE `One`";
8137     r = run_query(href, 0, query);
8138     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8139 
8140     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8141     r = run_query(hdb, 0, query);
8142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8143 
8144     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
8145     r = run_query(href, 0, query);
8146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8147 
8148     /* primary keys don't match */
8149     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8150     ok(r == ERROR_DATATYPE_MISMATCH,
8151        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8152 
8153     /* nothing in MergeErrors */
8154     query = "SELECT * FROM `MergeErrors`";
8155     r = do_query(hdb, query, &hrec);
8156     ok(r == ERROR_BAD_QUERY_SYNTAX,
8157        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8158 
8159     query = "DROP TABLE `One`";
8160     r = run_query(hdb, 0, query);
8161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8162 
8163     query = "DROP TABLE `One`";
8164     r = run_query(href, 0, query);
8165     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8166 
8167     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8168     r = run_query(hdb, 0, query);
8169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8170 
8171     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
8172     r = run_query(href, 0, query);
8173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8174 
8175     /* number of primary keys doesn't match */
8176     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8177     ok(r == ERROR_DATATYPE_MISMATCH,
8178        "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8179 
8180     /* nothing in MergeErrors */
8181     query = "SELECT * FROM `MergeErrors`";
8182     r = do_query(hdb, query, &hrec);
8183     ok(r == ERROR_BAD_QUERY_SYNTAX,
8184        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8185 
8186     query = "DROP TABLE `One`";
8187     r = run_query(hdb, 0, query);
8188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8189 
8190     query = "DROP TABLE `One`";
8191     r = run_query(href, 0, query);
8192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8193 
8194     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8195     r = run_query(hdb, 0, query);
8196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8197 
8198     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8199     r = run_query(href, 0, query);
8200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8201 
8202     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8203     r = run_query(href, 0, query);
8204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8205 
8206     /* number of columns doesn't match */
8207     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8209 
8210     query = "SELECT * FROM `One`";
8211     r = do_query(hdb, query, &hrec);
8212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8213 
8214     r = MsiRecordGetInteger(hrec, 1);
8215     ok(r == 1, "Expected 1, got %d\n", r);
8216 
8217     r = MsiRecordGetInteger(hrec, 2);
8218     ok(r == 2, "Expected 2, got %d\n", r);
8219 
8220     r = MsiRecordGetInteger(hrec, 3);
8221     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8222 
8223     MsiCloseHandle(hrec);
8224 
8225     /* nothing in MergeErrors */
8226     query = "SELECT * FROM `MergeErrors`";
8227     r = do_query(hdb, query, &hrec);
8228     ok(r == ERROR_BAD_QUERY_SYNTAX,
8229        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8230 
8231     query = "DROP TABLE `One`";
8232     r = run_query(hdb, 0, query);
8233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8234 
8235     query = "DROP TABLE `One`";
8236     r = run_query(href, 0, query);
8237     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8238 
8239     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8240     r = run_query(hdb, 0, query);
8241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8242 
8243     query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8244     r = run_query(href, 0, query);
8245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8246 
8247     query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8248     r = run_query(href, 0, query);
8249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8250 
8251     /* number of columns doesn't match */
8252     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8254 
8255     query = "SELECT * FROM `One`";
8256     r = do_query(hdb, query, &hrec);
8257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8258 
8259     r = MsiRecordGetInteger(hrec, 1);
8260     ok(r == 1, "Expected 1, got %d\n", r);
8261 
8262     r = MsiRecordGetInteger(hrec, 2);
8263     ok(r == 2, "Expected 2, got %d\n", r);
8264 
8265     r = MsiRecordGetInteger(hrec, 3);
8266     ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8267 
8268     MsiCloseHandle(hrec);
8269 
8270     /* nothing in MergeErrors */
8271     query = "SELECT * FROM `MergeErrors`";
8272     r = do_query(hdb, query, &hrec);
8273     ok(r == ERROR_BAD_QUERY_SYNTAX,
8274        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8275 
8276     query = "DROP TABLE `One`";
8277     r = run_query(hdb, 0, query);
8278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8279 
8280     query = "DROP TABLE `One`";
8281     r = run_query(href, 0, query);
8282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8283 
8284     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8285     r = run_query(hdb, 0, query);
8286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8287 
8288     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
8289     r = run_query(hdb, 0, query);
8290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8291 
8292     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8293     r = run_query(hdb, 0, query);
8294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8295 
8296     query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8297     r = run_query(href, 0, query);
8298     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8299 
8300     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8301     r = run_query(href, 0, query);
8302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8303 
8304     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
8305     r = run_query(href, 0, query);
8306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8307 
8308     /* primary keys match, rows do not */
8309     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8310     ok(r == ERROR_FUNCTION_FAILED,
8311        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8312 
8313     /* nothing in MergeErrors */
8314     query = "SELECT * FROM `MergeErrors`";
8315     r = do_query(hdb, query, &hrec);
8316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8317 
8318     size = MAX_PATH;
8319     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8321     ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8322 
8323     r = MsiRecordGetInteger(hrec, 2);
8324     ok(r == 2, "Expected 2, got %d\n", r);
8325 
8326     MsiCloseHandle(hrec);
8327 
8328     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8330 
8331     r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8333 
8334     size = MAX_PATH;
8335     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8337     ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8338 
8339     size = MAX_PATH;
8340     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8342     ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8343        "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8344 
8345     MsiCloseHandle(hrec);
8346 
8347     r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8349 
8350     size = MAX_PATH;
8351     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8353     ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8354 
8355     size = MAX_PATH;
8356     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8358     ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8359 
8360     MsiCloseHandle(hrec);
8361     MsiViewClose(hview);
8362     MsiCloseHandle(hview);
8363 
8364     query = "DROP TABLE `MergeErrors`";
8365     r = run_query(hdb, 0, query);
8366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8367 
8368     query = "DROP TABLE `One`";
8369     r = run_query(hdb, 0, query);
8370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8371 
8372     query = "DROP TABLE `One`";
8373     r = run_query(href, 0, query);
8374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8375 
8376     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8377     r = run_query(href, 0, query);
8378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8379 
8380     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8381     r = run_query(href, 0, query);
8382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8383 
8384     /* table from merged database is not in target database */
8385     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8387 
8388     query = "SELECT * FROM `One`";
8389     r = do_query(hdb, query, &hrec);
8390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8391 
8392     r = MsiRecordGetInteger(hrec, 1);
8393     ok(r == 1, "Expected 1, got %d\n", r);
8394 
8395     size = MAX_PATH;
8396     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8398     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8399 
8400     MsiCloseHandle(hrec);
8401 
8402     /* nothing in MergeErrors */
8403     query = "SELECT * FROM `MergeErrors`";
8404     r = do_query(hdb, query, &hrec);
8405     ok(r == ERROR_BAD_QUERY_SYNTAX,
8406        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8407 
8408     query = "DROP TABLE `One`";
8409     r = run_query(hdb, 0, query);
8410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8411 
8412     query = "DROP TABLE `One`";
8413     r = run_query(href, 0, query);
8414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8415 
8416     query = "CREATE TABLE `One` ( "
8417             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8418     r = run_query(hdb, 0, query);
8419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8420 
8421     query = "CREATE TABLE `One` ( "
8422             "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8423     r = run_query(href, 0, query);
8424     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8425 
8426     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8427     r = run_query(href, 0, query);
8428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8429 
8430     /* primary key is string */
8431     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8433 
8434     query = "SELECT * FROM `One`";
8435     r = do_query(hdb, query, &hrec);
8436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8437 
8438     size = MAX_PATH;
8439     r = MsiRecordGetStringA(hrec, 1, buf, &size);
8440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8441     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8442 
8443     r = MsiRecordGetInteger(hrec, 2);
8444     ok(r == 1, "Expected 1, got %d\n", r);
8445 
8446     MsiCloseHandle(hrec);
8447 
8448     /* nothing in MergeErrors */
8449     query = "SELECT * FROM `MergeErrors`";
8450     r = do_query(hdb, query, &hrec);
8451     ok(r == ERROR_BAD_QUERY_SYNTAX,
8452        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8453 
8454     create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8455 
8456     GetCurrentDirectoryA(MAX_PATH, buf);
8457     r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8459 
8460     query = "DROP TABLE `One`";
8461     r = run_query(hdb, 0, query);
8462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8463 
8464     query = "DROP TABLE `One`";
8465     r = run_query(href, 0, query);
8466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8467 
8468     query = "CREATE TABLE `One` ( "
8469             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8470     r = run_query(hdb, 0, query);
8471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8472 
8473     query = "CREATE TABLE `One` ( "
8474             "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8475     r = run_query(href, 0, query);
8476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8477 
8478     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8479     r = run_query(href, 0, query);
8480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8481 
8482     /* code page does not match */
8483     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8485 
8486     query = "SELECT * FROM `One`";
8487     r = do_query(hdb, query, &hrec);
8488     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8489 
8490     r = MsiRecordGetInteger(hrec, 1);
8491     ok(r == 1, "Expected 1, got %d\n", r);
8492 
8493     size = MAX_PATH;
8494     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8496     ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8497 
8498     MsiCloseHandle(hrec);
8499 
8500     /* nothing in MergeErrors */
8501     query = "SELECT * FROM `MergeErrors`";
8502     r = do_query(hdb, query, &hrec);
8503     ok(r == ERROR_BAD_QUERY_SYNTAX,
8504        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8505 
8506     query = "DROP TABLE `One`";
8507     r = run_query(hdb, 0, query);
8508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8509 
8510     query = "DROP TABLE `One`";
8511     r = run_query(href, 0, query);
8512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8513 
8514     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8515     r = run_query(hdb, 0, query);
8516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8517 
8518     query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8519     r = run_query(href, 0, query);
8520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8521 
8522     create_file("binary.dat");
8523     hrec = MsiCreateRecord(1);
8524     MsiRecordSetStreamA(hrec, 1, "binary.dat");
8525 
8526     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8527     r = run_query(href, hrec, query);
8528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8529 
8530     MsiCloseHandle(hrec);
8531 
8532     /* binary data to merge */
8533     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8534     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8535 
8536     query = "SELECT * FROM `One`";
8537     r = do_query(hdb, query, &hrec);
8538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8539 
8540     r = MsiRecordGetInteger(hrec, 1);
8541     ok(r == 1, "Expected 1, got %d\n", r);
8542 
8543     size = MAX_PATH;
8544     ZeroMemory(buf, MAX_PATH);
8545     r = MsiRecordReadStream(hrec, 2, buf, &size);
8546     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8547     ok(!lstrcmpA(buf, "binary.dat\n"),
8548        "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8549 
8550     MsiCloseHandle(hrec);
8551 
8552     /* nothing in MergeErrors */
8553     query = "SELECT * FROM `MergeErrors`";
8554     r = do_query(hdb, query, &hrec);
8555     ok(r == ERROR_BAD_QUERY_SYNTAX,
8556        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8557 
8558     query = "DROP TABLE `One`";
8559     r = run_query(hdb, 0, query);
8560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8561 
8562     query = "DROP TABLE `One`";
8563     r = run_query(href, 0, query);
8564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8565 
8566     query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8567     r = run_query(hdb, 0, query);
8568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8569     r = run_query(href, 0, query);
8570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8571 
8572     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8573     r = run_query(href, 0, query);
8574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8575 
8576     query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8577     r = run_query(href, 0, query);
8578     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8579 
8580     r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8581     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8582 
8583     query = "SELECT * FROM `One`";
8584     r = MsiDatabaseOpenViewA(hdb, query, &hview);
8585     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8586     r = MsiViewExecute(hview, 0);
8587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8588 
8589     r = MsiViewFetch(hview, &hrec);
8590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8591 
8592     r = MsiRecordGetInteger(hrec, 1);
8593     ok(r == 1, "Expected 1, got %d\n", r);
8594 
8595     size = MAX_PATH;
8596     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8598     ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8599 
8600     MsiCloseHandle(hrec);
8601 
8602     r = MsiViewFetch(hview, &hrec);
8603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8604 
8605     r = MsiRecordGetInteger(hrec, 1);
8606     ok(r == 2, "Expected 2, got %d\n", r);
8607 
8608     size = MAX_PATH;
8609     r = MsiRecordGetStringA(hrec, 2, buf, &size);
8610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8611     ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8612 
8613     MsiCloseHandle(hrec);
8614 
8615     r = MsiViewFetch(hview, &hrec);
8616     ok(r == ERROR_NO_MORE_ITEMS,
8617        "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8618 
8619     MsiViewClose(hview);
8620     MsiCloseHandle(hview);
8621 
8622     MsiCloseHandle(hdb);
8623     MsiCloseHandle(href);
8624     DeleteFileA(msifile);
8625     DeleteFileW(refdbW);
8626     DeleteFileA("codepage.idt");
8627     DeleteFileA("binary.dat");
8628 }
8629 
8630 static void test_select_with_tablenames(void)
8631 {
8632     MSIHANDLE hdb, view, rec;
8633     LPCSTR query;
8634     UINT r;
8635     int i;
8636 
8637     int vals[4][2] = {
8638         {1,12},
8639         {4,12},
8640         {1,15},
8641         {4,15}};
8642 
8643     hdb = create_db();
8644     ok(hdb, "failed to create db\n");
8645 
8646     /* Build a pair of tables with the same column names, but unique data */
8647     query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8648     r = run_query(hdb, 0, query);
8649     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8650 
8651     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8652     r = run_query(hdb, 0, query);
8653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8654 
8655     query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8656     r = run_query(hdb, 0, query);
8657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8658 
8659     query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8660     r = run_query(hdb, 0, query);
8661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8662 
8663     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8664     r = run_query(hdb, 0, query);
8665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8666 
8667     query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8668     r = run_query(hdb, 0, query);
8669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8670 
8671 
8672     /* Test that selection based on prefixing the column with the table
8673      * actually selects the right data */
8674 
8675     query = "SELECT T1.A, T2.B FROM T1,T2";
8676     r = MsiDatabaseOpenViewA(hdb, query, &view);
8677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8678     r = MsiViewExecute(view, 0);
8679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8680 
8681     for (i = 0; i < 4; i++)
8682     {
8683         r = MsiViewFetch(view, &rec);
8684         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8685 
8686         r = MsiRecordGetInteger(rec, 1);
8687         ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8688 
8689         r = MsiRecordGetInteger(rec, 2);
8690         ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8691 
8692         MsiCloseHandle(rec);
8693     }
8694 
8695     r = MsiViewFetch(view, &rec);
8696     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8697 
8698     MsiViewClose(view);
8699     MsiCloseHandle(view);
8700     MsiCloseHandle(hdb);
8701     DeleteFileA(msifile);
8702 }
8703 
8704 static const UINT ordervals[6][3] =
8705 {
8706     { MSI_NULL_INTEGER, 12, 13 },
8707     { 1, 2, 3 },
8708     { 6, 4, 5 },
8709     { 8, 9, 7 },
8710     { 10, 11, MSI_NULL_INTEGER },
8711     { 14, MSI_NULL_INTEGER, 15 }
8712 };
8713 
8714 static void test_insertorder(void)
8715 {
8716     MSIHANDLE hdb, view, rec;
8717     LPCSTR query;
8718     UINT r;
8719     int i;
8720 
8721     hdb = create_db();
8722     ok(hdb, "failed to create db\n");
8723 
8724     query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8725     r = run_query(hdb, 0, query);
8726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8727 
8728     query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8729     r = run_query(hdb, 0, query);
8730     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8731 
8732     query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8733     r = run_query(hdb, 0, query);
8734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8735 
8736     query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8737     r = run_query(hdb, 0, query);
8738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8739 
8740     query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8741     r = run_query(hdb, 0, query);
8742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8743 
8744     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8745     r = run_query(hdb, 0, query);
8746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8747 
8748     /* fails because the primary key already
8749      * has an MSI_NULL_INTEGER value set above
8750      */
8751     query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8752     r = run_query(hdb, 0, query);
8753     ok(r == ERROR_FUNCTION_FAILED,
8754        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8755 
8756     /* replicate the error where primary key is set twice */
8757     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8758     r = run_query(hdb, 0, query);
8759     ok(r == ERROR_FUNCTION_FAILED,
8760        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8761 
8762     query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8763     r = run_query(hdb, 0, query);
8764     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8765 
8766     query = "INSERT INTO `T` VALUES ( 16 )";
8767     r = run_query(hdb, 0, query);
8768     ok(r == ERROR_BAD_QUERY_SYNTAX,
8769        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8770 
8771     query = "INSERT INTO `T` VALUES ( 17, 18 )";
8772     r = run_query(hdb, 0, query);
8773     ok(r == ERROR_BAD_QUERY_SYNTAX,
8774        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8775 
8776     query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8777     r = run_query(hdb, 0, query);
8778     ok(r == ERROR_BAD_QUERY_SYNTAX,
8779        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8780 
8781     query = "SELECT * FROM `T`";
8782     r = MsiDatabaseOpenViewA(hdb, query, &view);
8783     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8784     r = MsiViewExecute(view, 0);
8785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8786 
8787     for (i = 0; i < 6; i++)
8788     {
8789         r = MsiViewFetch(view, &rec);
8790         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8791 
8792         r = MsiRecordGetInteger(rec, 1);
8793         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8794 
8795         r = MsiRecordGetInteger(rec, 2);
8796         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8797 
8798         r = MsiRecordGetInteger(rec, 3);
8799         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8800 
8801         MsiCloseHandle(rec);
8802     }
8803 
8804     r = MsiViewFetch(view, &rec);
8805     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8806 
8807     MsiViewClose(view);
8808     MsiCloseHandle(view);
8809 
8810     query = "DELETE FROM `T` WHERE `A` IS NULL";
8811     r = run_query(hdb, 0, query);
8812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8813 
8814     query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8815     r = run_query(hdb, 0, query);
8816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8817 
8818     query = "SELECT * FROM `T`";
8819     r = MsiDatabaseOpenViewA(hdb, query, &view);
8820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8821     r = MsiViewExecute(view, 0);
8822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8823 
8824     for (i = 0; i < 6; i++)
8825     {
8826         r = MsiViewFetch(view, &rec);
8827         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8828 
8829         r = MsiRecordGetInteger(rec, 1);
8830         ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8831 
8832         r = MsiRecordGetInteger(rec, 2);
8833         ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8834 
8835         r = MsiRecordGetInteger(rec, 3);
8836         ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8837 
8838         MsiCloseHandle(rec);
8839     }
8840 
8841     r = MsiViewFetch(view, &rec);
8842     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8843 
8844     MsiViewClose(view);
8845     MsiCloseHandle(view);
8846     MsiCloseHandle(hdb);
8847     DeleteFileA(msifile);
8848 }
8849 
8850 static void test_columnorder(void)
8851 {
8852     MSIHANDLE hdb, view, rec;
8853     char buf[MAX_PATH];
8854     LPCSTR query;
8855     DWORD sz;
8856     UINT r;
8857 
8858     hdb = create_db();
8859     ok(hdb, "failed to create db\n");
8860 
8861     /* Each column is a slot:
8862      * ---------------------
8863      * | B | C | A | E | D |
8864      * ---------------------
8865      *
8866      * When a column is selected as a primary key,
8867      * the column occupying the nth primary key slot is swapped
8868      * with the current position of the primary key in question:
8869      *
8870      * set primary key `D`
8871      * ---------------------    ---------------------
8872      * | B | C | A | E | D | -> | D | C | A | E | B |
8873      * ---------------------    ---------------------
8874      *
8875      * set primary key `E`
8876      * ---------------------    ---------------------
8877      * | D | C | A | E | B | -> | D | E | A | C | B |
8878      * ---------------------    ---------------------
8879      */
8880 
8881     query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8882             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8883             "PRIMARY KEY `D`, `E`)";
8884     r = run_query(hdb, 0, query);
8885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8886 
8887     query = "SELECT * FROM `T`";
8888     r = MsiDatabaseOpenViewA(hdb, query, &view);
8889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8890 
8891     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8893 
8894     sz = MAX_PATH;
8895     lstrcpyA(buf, "kiwi");
8896     r = MsiRecordGetStringA(rec, 1, buf, &sz);
8897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8898     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8899 
8900     sz = MAX_PATH;
8901     lstrcpyA(buf, "kiwi");
8902     r = MsiRecordGetStringA(rec, 2, buf, &sz);
8903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8904     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8905 
8906     sz = MAX_PATH;
8907     lstrcpyA(buf, "kiwi");
8908     r = MsiRecordGetStringA(rec, 3, buf, &sz);
8909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8910     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8911 
8912     sz = MAX_PATH;
8913     lstrcpyA(buf, "kiwi");
8914     r = MsiRecordGetStringA(rec, 4, buf, &sz);
8915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8916     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8917 
8918     sz = MAX_PATH;
8919     lstrcpyA(buf, "kiwi");
8920     r = MsiRecordGetStringA(rec, 5, buf, &sz);
8921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8922     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8923 
8924     MsiCloseHandle(rec);
8925 
8926     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8927     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8928 
8929     sz = MAX_PATH;
8930     lstrcpyA(buf, "kiwi");
8931     r = MsiRecordGetStringA(rec, 1, buf, &sz);
8932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8933     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8934 
8935     sz = MAX_PATH;
8936     lstrcpyA(buf, "kiwi");
8937     r = MsiRecordGetStringA(rec, 2, buf, &sz);
8938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8939     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8940 
8941     sz = MAX_PATH;
8942     lstrcpyA(buf, "kiwi");
8943     r = MsiRecordGetStringA(rec, 3, buf, &sz);
8944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8945     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8946 
8947     sz = MAX_PATH;
8948     lstrcpyA(buf, "kiwi");
8949     r = MsiRecordGetStringA(rec, 4, buf, &sz);
8950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8951     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8952 
8953     sz = MAX_PATH;
8954     lstrcpyA(buf, "kiwi");
8955     r = MsiRecordGetStringA(rec, 5, buf, &sz);
8956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8957     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8958 
8959     MsiCloseHandle(rec);
8960     MsiViewClose(view);
8961     MsiCloseHandle(view);
8962 
8963     query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8964             "VALUES ( 1, 2, 'a', 3, 'bc' )";
8965     r = run_query(hdb, 0, query);
8966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8967 
8968     query = "SELECT * FROM `T`";
8969     r = do_query(hdb, query, &rec);
8970     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8971 
8972     sz = MAX_PATH;
8973     lstrcpyA(buf, "kiwi");
8974     r = MsiRecordGetStringA(rec, 1, buf, &sz);
8975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8976     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8977 
8978     r = MsiRecordGetInteger(rec, 2);
8979     ok(r == 3, "Expected 3, got %d\n", r);
8980 
8981     sz = MAX_PATH;
8982     lstrcpyA(buf, "kiwi");
8983     r = MsiRecordGetStringA(rec, 3, 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     r = MsiRecordGetInteger(rec, 4);
8988     ok(r == 2, "Expected 2, got %d\n", r);
8989 
8990     r = MsiRecordGetInteger(rec, 5);
8991     ok(r == 1, "Expected 1, got %d\n", r);
8992 
8993     MsiCloseHandle(rec);
8994 
8995     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8996     r = MsiDatabaseOpenViewA(hdb, query, &view);
8997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8998     r = MsiViewExecute(view, 0);
8999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9000 
9001     r = MsiViewFetch(view, &rec);
9002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9003 
9004     sz = MAX_PATH;
9005     lstrcpyA(buf, "kiwi");
9006     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9008     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9009 
9010     r = MsiRecordGetInteger(rec, 2);
9011     ok(r == 1, "Expected 1, got %d\n", r);
9012 
9013     sz = MAX_PATH;
9014     lstrcpyA(buf, "kiwi");
9015     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9017     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9018 
9019     MsiCloseHandle(rec);
9020 
9021     r = MsiViewFetch(view, &rec);
9022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9023 
9024     sz = MAX_PATH;
9025     lstrcpyA(buf, "kiwi");
9026     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9028     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9029 
9030     r = MsiRecordGetInteger(rec, 2);
9031     ok(r == 2, "Expected 2, got %d\n", r);
9032 
9033     sz = MAX_PATH;
9034     lstrcpyA(buf, "kiwi");
9035     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9036     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9037     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9038 
9039     MsiCloseHandle(rec);
9040 
9041     r = MsiViewFetch(view, &rec);
9042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9043 
9044     sz = MAX_PATH;
9045     lstrcpyA(buf, "kiwi");
9046     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9048     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9049 
9050     r = MsiRecordGetInteger(rec, 2);
9051     ok(r == 3, "Expected 3, got %d\n", r);
9052 
9053     sz = MAX_PATH;
9054     lstrcpyA(buf, "kiwi");
9055     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9057     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9058 
9059     MsiCloseHandle(rec);
9060 
9061     r = MsiViewFetch(view, &rec);
9062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9063 
9064     sz = MAX_PATH;
9065     lstrcpyA(buf, "kiwi");
9066     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9068     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9069 
9070     r = MsiRecordGetInteger(rec, 2);
9071     ok(r == 4, "Expected 4, got %d\n", r);
9072 
9073     sz = MAX_PATH;
9074     lstrcpyA(buf, "kiwi");
9075     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9077     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9078 
9079     MsiCloseHandle(rec);
9080 
9081     r = MsiViewFetch(view, &rec);
9082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9083 
9084     sz = MAX_PATH;
9085     lstrcpyA(buf, "kiwi");
9086     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9088     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9089 
9090     r = MsiRecordGetInteger(rec, 2);
9091     ok(r == 5, "Expected 5, got %d\n", r);
9092 
9093     sz = MAX_PATH;
9094     lstrcpyA(buf, "kiwi");
9095     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9096     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9097     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9098 
9099     MsiCloseHandle(rec);
9100 
9101     r = MsiViewFetch(view, &rec);
9102     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9103 
9104     MsiViewClose(view);
9105     MsiCloseHandle(view);
9106 
9107     query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
9108             "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
9109             "PRIMARY KEY `C`, `A`, `D`)";
9110     r = run_query(hdb, 0, query);
9111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9112 
9113     query = "SELECT * FROM `Z`";
9114     r = MsiDatabaseOpenViewA(hdb, query, &view);
9115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9116 
9117     r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
9118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9119 
9120     sz = MAX_PATH;
9121     lstrcpyA(buf, "kiwi");
9122     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9124     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9125 
9126     sz = MAX_PATH;
9127     lstrcpyA(buf, "kiwi");
9128     r = MsiRecordGetStringA(rec, 2, buf, &sz);
9129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9130     ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
9131 
9132     sz = MAX_PATH;
9133     lstrcpyA(buf, "kiwi");
9134     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9136     ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
9137 
9138     sz = MAX_PATH;
9139     lstrcpyA(buf, "kiwi");
9140     r = MsiRecordGetStringA(rec, 4, buf, &sz);
9141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9142     ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
9143 
9144     sz = MAX_PATH;
9145     lstrcpyA(buf, "kiwi");
9146     r = MsiRecordGetStringA(rec, 5, buf, &sz);
9147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9148     ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9149 
9150     MsiCloseHandle(rec);
9151 
9152     r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
9153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9154 
9155     sz = MAX_PATH;
9156     lstrcpyA(buf, "kiwi");
9157     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9159     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9160 
9161     sz = MAX_PATH;
9162     lstrcpyA(buf, "kiwi");
9163     r = MsiRecordGetStringA(rec, 2, buf, &sz);
9164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9165     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9166 
9167     sz = MAX_PATH;
9168     lstrcpyA(buf, "kiwi");
9169     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9171     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9172 
9173     sz = MAX_PATH;
9174     lstrcpyA(buf, "kiwi");
9175     r = MsiRecordGetStringA(rec, 4, buf, &sz);
9176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9177     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9178 
9179     sz = MAX_PATH;
9180     lstrcpyA(buf, "kiwi");
9181     r = MsiRecordGetStringA(rec, 5, buf, &sz);
9182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9183     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9184 
9185     MsiCloseHandle(rec);
9186     MsiViewClose(view);
9187     MsiCloseHandle(view);
9188 
9189     query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
9190             "VALUES ( 1, 2, 'a', 3, 'bc' )";
9191     r = run_query(hdb, 0, query);
9192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9193 
9194     query = "SELECT * FROM `Z`";
9195     r = do_query(hdb, query, &rec);
9196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9197 
9198     r = MsiRecordGetInteger(rec, 1);
9199     ok(r == 2, "Expected 2, got %d\n", r);
9200 
9201     sz = MAX_PATH;
9202     lstrcpyA(buf, "kiwi");
9203     r = MsiRecordGetStringA(rec, 2, buf, &sz);
9204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9205     ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
9206 
9207     sz = MAX_PATH;
9208     lstrcpyA(buf, "kiwi");
9209     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9211     ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
9212 
9213     r = MsiRecordGetInteger(rec, 4);
9214     ok(r == 3, "Expected 3, got %d\n", r);
9215 
9216     r = MsiRecordGetInteger(rec, 5);
9217     ok(r == 1, "Expected 1, got %d\n", r);
9218 
9219     MsiCloseHandle(rec);
9220 
9221     query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
9222     r = MsiDatabaseOpenViewA(hdb, query, &view);
9223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9224     r = MsiViewExecute(view, 0);
9225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9226 
9227     r = MsiViewFetch(view, &rec);
9228     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9229 
9230     sz = MAX_PATH;
9231     lstrcpyA(buf, "kiwi");
9232     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9234     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9235 
9236     r = MsiRecordGetInteger(rec, 2);
9237     ok(r == 1, "Expected 1, got %d\n", r);
9238 
9239     sz = MAX_PATH;
9240     lstrcpyA(buf, "kiwi");
9241     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9243     ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9244 
9245     MsiCloseHandle(rec);
9246 
9247     r = MsiViewFetch(view, &rec);
9248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9249 
9250     sz = MAX_PATH;
9251     lstrcpyA(buf, "kiwi");
9252     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9254     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9255 
9256     r = MsiRecordGetInteger(rec, 2);
9257     ok(r == 2, "Expected 2, got %d\n", r);
9258 
9259     sz = MAX_PATH;
9260     lstrcpyA(buf, "kiwi");
9261     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9263     ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9264 
9265     MsiCloseHandle(rec);
9266 
9267     r = MsiViewFetch(view, &rec);
9268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9269 
9270     sz = MAX_PATH;
9271     lstrcpyA(buf, "kiwi");
9272     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9274     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9275 
9276     r = MsiRecordGetInteger(rec, 2);
9277     ok(r == 3, "Expected 3, got %d\n", r);
9278 
9279     sz = MAX_PATH;
9280     lstrcpyA(buf, "kiwi");
9281     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9283     ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9284 
9285     MsiCloseHandle(rec);
9286 
9287     r = MsiViewFetch(view, &rec);
9288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9289 
9290     sz = MAX_PATH;
9291     lstrcpyA(buf, "kiwi");
9292     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9294     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9295 
9296     r = MsiRecordGetInteger(rec, 2);
9297     ok(r == 4, "Expected 4, got %d\n", r);
9298 
9299     sz = MAX_PATH;
9300     lstrcpyA(buf, "kiwi");
9301     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9303     ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9304 
9305     MsiCloseHandle(rec);
9306 
9307     r = MsiViewFetch(view, &rec);
9308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9309 
9310     sz = MAX_PATH;
9311     lstrcpyA(buf, "kiwi");
9312     r = MsiRecordGetStringA(rec, 1, buf, &sz);
9313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9314     ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9315 
9316     r = MsiRecordGetInteger(rec, 2);
9317     ok(r == 5, "Expected 5, got %d\n", r);
9318 
9319     sz = MAX_PATH;
9320     lstrcpyA(buf, "kiwi");
9321     r = MsiRecordGetStringA(rec, 3, buf, &sz);
9322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9323     ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9324 
9325     MsiCloseHandle(rec);
9326 
9327     r = MsiViewFetch(view, &rec);
9328     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9329 
9330     MsiViewClose(view);
9331     MsiCloseHandle(view);
9332 
9333     MsiCloseHandle(hdb);
9334     DeleteFileA(msifile);
9335 }
9336 
9337 static void test_createtable(void)
9338 {
9339     MSIHANDLE hdb, htab = 0, hrec = 0;
9340     LPCSTR query;
9341     UINT res;
9342     DWORD size;
9343     char buffer[0x20];
9344 
9345     hdb = create_db();
9346     ok(hdb, "failed to create db\n");
9347 
9348     query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9349     res = MsiDatabaseOpenViewA( hdb, query, &htab );
9350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9351     if(res == ERROR_SUCCESS )
9352     {
9353         res = MsiViewExecute( htab, hrec );
9354         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9355 
9356         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9357         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9358 
9359         size = sizeof(buffer);
9360         res = MsiRecordGetStringA(hrec, 1, buffer, &size );
9361         todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9362         MsiCloseHandle( hrec );
9363 
9364         res = MsiViewClose( htab );
9365         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9366 
9367         res = MsiCloseHandle( htab );
9368         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9369     }
9370 
9371     query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9372     res = MsiDatabaseOpenViewA( hdb, query, &htab );
9373     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9374     if(res == ERROR_SUCCESS )
9375     {
9376         res = MsiViewExecute( htab, 0 );
9377         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9378 
9379         res = MsiViewClose( htab );
9380         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9381 
9382         res = MsiCloseHandle( htab );
9383         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9384 
9385         query = "SELECT * FROM `a`";
9386         res = MsiDatabaseOpenViewA( hdb, query, &htab );
9387         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9388 
9389         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9390         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9391 
9392         buffer[0] = 0;
9393         size = sizeof(buffer);
9394         res = MsiRecordGetStringA(hrec, 1, buffer, &size );
9395         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9396         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9397         MsiCloseHandle( hrec );
9398 
9399         res = MsiViewClose( htab );
9400         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9401 
9402         res = MsiCloseHandle( htab );
9403         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9404 
9405         res = MsiDatabaseCommit(hdb);
9406         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9407 
9408         res = MsiCloseHandle(hdb);
9409         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9410 
9411         res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
9412         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9413 
9414         query = "SELECT * FROM `a`";
9415         res = MsiDatabaseOpenViewA( hdb, query, &htab );
9416         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9417 
9418         res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9419         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9420 
9421         buffer[0] = 0;
9422         size = sizeof(buffer);
9423         res = MsiRecordGetStringA(hrec, 1, buffer, &size );
9424         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9425         ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9426 
9427         res = MsiCloseHandle( hrec );
9428         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9429 
9430         res = MsiViewClose( htab );
9431         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9432 
9433         res = MsiCloseHandle( htab );
9434         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9435     }
9436 
9437     res = MsiDatabaseCommit(hdb);
9438     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9439 
9440     res = MsiCloseHandle(hdb);
9441     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9442 
9443     DeleteFileA(msifile);
9444 }
9445 
9446 static void test_embedded_nulls(void)
9447 {
9448     static const char control_table[] =
9449         "Dialog\tText\n"
9450         "s72\tL0\n"
9451         "Control\tDialog\n"
9452         "LicenseAgreementDlg\ttext\x11\x19text\0text";
9453     UINT r, sz;
9454     MSIHANDLE hdb, hrec;
9455     char buffer[32];
9456 
9457     r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
9458     ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
9459 
9460     GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
9461     write_file( "temp_file", control_table, sizeof(control_table) );
9462     r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
9463     ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
9464     DeleteFileA( "temp_file" );
9465 
9466     r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
9467     ok( r == ERROR_SUCCESS, "query failed %u\n", r );
9468 
9469     buffer[0] = 0;
9470     sz = sizeof(buffer);
9471     r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
9472     ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
9473     ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
9474 
9475     MsiCloseHandle( hrec );
9476     MsiCloseHandle( hdb );
9477     DeleteFileA( msifile );
9478 }
9479 
9480 static void test_select_column_names(void)
9481 {
9482     MSIHANDLE hdb = 0, rec, rec2, view;
9483     char buffer[32];
9484     UINT r, size;
9485 
9486     DeleteFileA(msifile);
9487 
9488     r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
9489     ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r );
9490 
9491     r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)");
9492     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9493 
9494     r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" );
9495     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9496 
9497     r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9498     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9499 
9500     r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9501     todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
9502 
9503     r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9504     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9505 
9506     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" );
9507     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9508 
9509     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" );
9510     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9511 
9512     r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" );
9513     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9514 
9515     r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" );
9516     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9517 
9518     r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" );
9519     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9520 
9521     r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" );
9522     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9523 
9524     r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" );
9525     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9526 
9527     r = MsiDatabaseOpenViewA( hdb, "SELECT '' FROM `t`", &view );
9528     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9529 
9530     r = MsiViewExecute( view, 0 );
9531     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9532 
9533     r = MsiViewFetch( view, &rec );
9534     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9535     r = MsiRecordGetFieldCount( rec );
9536     ok( r == 1, "got %u\n",  r );
9537     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec2 );
9538     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9539     r = MsiRecordGetFieldCount( rec2 );
9540     ok( r == 1, "got %u\n",  r );
9541     size = sizeof(buffer);
9542     memset( buffer, 0x55, sizeof(buffer) );
9543     r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9544     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9545     ok( !buffer[0], "got \"%s\"\n", buffer );
9546     MsiCloseHandle( rec2 );
9547     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec2 );
9548     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9549     r = MsiRecordGetFieldCount( rec2 );
9550     ok( r == 1, "got %u\n",  r );
9551     size = sizeof(buffer);
9552     memset( buffer, 0x55, sizeof(buffer) );
9553     r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9554     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9555     ok( !lstrcmpA( buffer, "f0" ), "got \"%s\"\n", buffer );
9556     MsiCloseHandle( rec2 );
9557 
9558     size = sizeof(buffer);
9559     memset( buffer, 0x55, sizeof(buffer) );
9560     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9561     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9562     ok( !buffer[0], "got \"%s\"\n", buffer );
9563     MsiCloseHandle( rec );
9564 
9565     r = MsiViewFetch( view, &rec );
9566     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9567     size = sizeof(buffer);
9568     memset( buffer, 0x55, sizeof(buffer) );
9569     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9570     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9571     ok( !buffer[0], "got \"%s\"\n", buffer );
9572     MsiCloseHandle( rec );
9573 
9574     r = MsiViewFetch( view, &rec );
9575     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9576     MsiCloseHandle( rec );
9577 
9578     MsiViewClose( view );
9579     MsiCloseHandle( view );
9580 
9581     r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '' FROM `t`", &view );
9582     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9583 
9584     r = MsiViewExecute( view, 0 );
9585     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9586 
9587     r = MsiViewFetch( view, &rec );
9588     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9589     r = MsiRecordGetFieldCount( rec );
9590     ok( r == 2, "got %u\n",  r );
9591     size = sizeof(buffer);
9592     memset( buffer, 0x55, sizeof(buffer) );
9593     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9594     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9595     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9596     MsiCloseHandle( rec );
9597 
9598     r = MsiViewFetch( view, &rec );
9599     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9600     size = sizeof(buffer);
9601     memset( buffer, 0x55, sizeof(buffer) );
9602     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9603     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9604     ok( !buffer[0], "got \"%s\"\n", buffer );
9605     MsiCloseHandle( rec );
9606 
9607     r = MsiViewFetch( view, &rec );
9608     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9609     MsiCloseHandle( rec );
9610 
9611     MsiViewClose( view );
9612     MsiCloseHandle( view );
9613 
9614     r = MsiDatabaseOpenViewA( hdb, "SELECT '', `a` FROM `t`", &view );
9615     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9616 
9617     r = MsiViewExecute( view, 0 );
9618     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9619 
9620     r = MsiViewFetch( view, &rec );
9621     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9622     r = MsiRecordGetFieldCount( rec );
9623     ok( r == 2, "got %u\n",  r );
9624     size = sizeof(buffer);
9625     memset( buffer, 0x55, sizeof(buffer) );
9626     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9627     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9628     ok( !buffer[0], "got \"%s\"\n", buffer );
9629     size = sizeof(buffer);
9630     memset( buffer, 0x55, sizeof(buffer) );
9631     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9632     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9633     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9634     MsiCloseHandle( rec );
9635 
9636     r = MsiViewFetch( view, &rec );
9637     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9638     size = sizeof(buffer);
9639     memset( buffer, 0x55, sizeof(buffer) );
9640     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9641     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9642     ok( !buffer[0], "got \"%s\"\n", buffer );
9643     size = sizeof(buffer);
9644     memset( buffer, 0x55, sizeof(buffer) );
9645     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9646     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9647     ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9648     MsiCloseHandle( rec );
9649 
9650     r = MsiViewFetch( view, &rec );
9651     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9652     MsiCloseHandle( rec );
9653 
9654     MsiViewClose( view );
9655     MsiCloseHandle( view );
9656 
9657     r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '', `b` FROM `t`", &view );
9658     ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9659 
9660     r = MsiViewExecute( view, 0 );
9661     ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9662 
9663     r = MsiViewFetch( view, &rec );
9664     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9665     r = MsiRecordGetFieldCount( rec );
9666     ok( r == 3, "got %u\n",  r );
9667     size = sizeof(buffer);
9668     memset( buffer, 0x55, sizeof(buffer) );
9669     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9670     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9671     ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9672     size = sizeof(buffer);
9673     memset( buffer, 0x55, sizeof(buffer) );
9674     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9675     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9676     ok( !buffer[0], "got \"%s\"\n", buffer );
9677     size = sizeof(buffer);
9678     memset( buffer, 0x55, sizeof(buffer) );
9679     r = MsiRecordGetStringA( rec, 3, buffer, &size );
9680     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9681     ok( !lstrcmpA( buffer, "2" ), "got \"%s\"\n", buffer );
9682     MsiCloseHandle( rec );
9683 
9684     r = MsiViewFetch( view, &rec );
9685     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9686     size = sizeof(buffer);
9687     memset( buffer, 0x55, sizeof(buffer) );
9688     r = MsiRecordGetStringA( rec, 1, buffer, &size );
9689     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9690     ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9691     size = sizeof(buffer);
9692     memset( buffer, 0x55, sizeof(buffer) );
9693     r = MsiRecordGetStringA( rec, 2, buffer, &size );
9694     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9695     ok( !buffer[0], "got \"%s\"\n", buffer );
9696     size = sizeof(buffer);
9697     memset( buffer, 0x55, sizeof(buffer) );
9698     r = MsiRecordGetStringA( rec, 3, buffer, &size );
9699     ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9700     ok( !lstrcmpA( buffer, "4" ), "got \"%s\"\n", buffer );
9701     MsiCloseHandle( rec );
9702 
9703     r = MsiViewFetch( view, &rec );
9704     ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9705     MsiCloseHandle( rec );
9706 
9707     MsiViewClose( view );
9708     MsiCloseHandle( view );
9709 
9710     r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" );
9711     ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9712 
9713     r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" );
9714     todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9715 
9716     r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" );
9717     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9718 
9719     r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" );
9720     ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9721 
9722     r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" );
9723     todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9724 
9725     r = MsiCloseHandle( hdb );
9726     ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r);
9727 }
9728 
9729 START_TEST(db)
9730 {
9731     test_msidatabase();
9732     test_msiinsert();
9733     test_msidecomposedesc();
9734     test_msibadqueries();
9735     test_viewmodify();
9736     test_viewgetcolumninfo();
9737     test_getcolinfo();
9738     test_msiexport();
9739     test_longstrings();
9740     test_streamtable();
9741     test_binary();
9742     test_where_not_in_selected();
9743     test_where();
9744     test_msiimport();
9745     test_binary_import();
9746     test_markers();
9747     test_handle_limit();
9748     test_try_transform();
9749     test_join();
9750     test_temporary_table();
9751     test_alter();
9752     test_integers();
9753     test_update();
9754     test_special_tables();
9755     test_tables_order();
9756     test_rows_order();
9757     test_select_markers();
9758     test_viewmodify_update();
9759     test_viewmodify_assign();
9760     test_stringtable();
9761     test_viewmodify_delete();
9762     test_defaultdatabase();
9763     test_order();
9764     test_viewmodify_delete_temporary();
9765     test_deleterow();
9766     test_quotes();
9767     test_carriagereturn();
9768     test_noquotes();
9769     test_forcecodepage();
9770     test_viewmodify_refresh();
9771     test_where_viewmodify();
9772     test_storages_table();
9773     test_dbtopackage();
9774     test_droptable();
9775     test_dbmerge();
9776     test_select_with_tablenames();
9777     test_insertorder();
9778     test_columnorder();
9779     test_suminfo_import();
9780     test_createtable();
9781     test_collation();
9782     test_embedded_nulls();
9783     test_select_column_names();
9784 }
9785