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