Partial merge of condrv_restructure branch r65657.
[reactos.git] / rostests / winetests / msi / db.c
1 /*
2 * Copyright (C) 2005 Mike McCormack for CodeWeavers
3 *
4 * A test program for MSI database files.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define COBJMACROS
22
23 #include <stdio.h>
24
25 #include <windows.h>
26 #include <msi.h>
27 #include <msidefs.h>
28 #include <msiquery.h>
29
30 #include <objidl.h>
31
32 #include "wine/test.h"
33
34 static const char *msifile = "winetest-db.msi";
35 static const char *msifile2 = "winetst2-db.msi";
36 static const char *mstfile = "winetst-db.mst";
37 static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','-','d','b','.','m','s','i',0};
38 static const WCHAR msifile2W[] = {'w','i','n','e','t','s','t','2','-','d','b','.','m','s','i',0};
39
40 static void test_msidatabase(void)
41 {
42 MSIHANDLE hdb = 0, hdb2 = 0;
43 UINT res;
44
45 DeleteFileW(msifileW);
46
47 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb );
48 ok( res == ERROR_OPEN_FAILED, "expected failure\n");
49
50 res = MsiOpenDatabaseW( msifileW, (LPWSTR)0xff, &hdb );
51 ok( res == ERROR_INVALID_PARAMETER, "expected failure\n");
52
53 res = MsiCloseHandle( hdb );
54 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
55
56 /* create an empty database */
57 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
58 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
59
60 res = MsiDatabaseCommit( hdb );
61 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
62
63 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
64
65 res = MsiCloseHandle( hdb );
66 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
67 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
68 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
69
70 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
71
72 res = MsiDatabaseCommit( hdb2 );
73 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
74
75 res = MsiCloseHandle( hdb2 );
76 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
77
78 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
79 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
80
81 res = MsiCloseHandle( hdb2 );
82 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
83
84 ok( GetFileAttributesA( msifile2 ) == INVALID_FILE_ATTRIBUTES, "uncommitted database should not exist\n");
85
86 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
87 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
88
89 res = MsiDatabaseCommit( hdb2 );
90 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
91
92 res = MsiCloseHandle( hdb2 );
93 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
94
95 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "committed database should exist\n");
96
97 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb );
98 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
99
100 res = MsiDatabaseCommit( hdb );
101 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
102
103 res = MsiCloseHandle( hdb );
104 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
105
106 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_DIRECT, &hdb );
107 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
108
109 res = MsiCloseHandle( hdb );
110 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
111
112 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_TRANSACT, &hdb );
113 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
114
115 res = MsiCloseHandle( hdb );
116 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
117 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
118
119 /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
120 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
121 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
122
123 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
124
125 res = MsiCloseHandle( hdb );
126 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
127
128 ok( GetFileAttributesA( msifile ) == INVALID_FILE_ATTRIBUTES, "database should exist\n");
129
130 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
131 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
132
133 res = MsiDatabaseCommit( hdb );
134 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
135
136 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
137
138 res = MsiCloseHandle( hdb );
139 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
140
141 res = DeleteFileA( msifile2 );
142 ok( res == TRUE, "Failed to delete database\n" );
143
144 res = DeleteFileA( msifile );
145 ok( res == TRUE, "Failed to delete database\n" );
146 }
147
148 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
149 {
150 MSIHANDLE hview = 0;
151 UINT r, ret;
152
153 if (phrec)
154 *phrec = 0;
155
156 /* open a select query */
157 r = MsiDatabaseOpenViewA(hdb, query, &hview);
158 if (r != ERROR_SUCCESS)
159 return r;
160 r = MsiViewExecute(hview, 0);
161 if (r != ERROR_SUCCESS)
162 return r;
163 ret = MsiViewFetch(hview, phrec);
164 r = MsiViewClose(hview);
165 if (r != ERROR_SUCCESS)
166 return r;
167 r = MsiCloseHandle(hview);
168 if (r != ERROR_SUCCESS)
169 return r;
170 return ret;
171 }
172
173 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
174 {
175 MSIHANDLE hview = 0;
176 UINT r;
177
178 r = MsiDatabaseOpenViewA(hdb, query, &hview);
179 if( r != ERROR_SUCCESS )
180 return r;
181
182 r = MsiViewExecute(hview, hrec);
183 if( r == ERROR_SUCCESS )
184 r = MsiViewClose(hview);
185 MsiCloseHandle(hview);
186 return r;
187 }
188
189 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
190 {
191 MSIHANDLE hview = 0;
192 UINT r;
193
194 r = MsiDatabaseOpenViewW(hdb, query, &hview);
195 if( r != ERROR_SUCCESS )
196 return r;
197
198 r = MsiViewExecute(hview, hrec);
199 if( r == ERROR_SUCCESS )
200 r = MsiViewClose(hview);
201 MsiCloseHandle(hview);
202 return r;
203 }
204
205 static UINT create_component_table( MSIHANDLE hdb )
206 {
207 return run_query( hdb, 0,
208 "CREATE TABLE `Component` ( "
209 "`Component` CHAR(72) NOT NULL, "
210 "`ComponentId` CHAR(38), "
211 "`Directory_` CHAR(72) NOT NULL, "
212 "`Attributes` SHORT NOT NULL, "
213 "`Condition` CHAR(255), "
214 "`KeyPath` CHAR(72) "
215 "PRIMARY KEY `Component`)" );
216 }
217
218 static UINT create_custom_action_table( MSIHANDLE hdb )
219 {
220 return run_query( hdb, 0,
221 "CREATE TABLE `CustomAction` ( "
222 "`Action` CHAR(72) NOT NULL, "
223 "`Type` SHORT NOT NULL, "
224 "`Source` CHAR(72), "
225 "`Target` CHAR(255) "
226 "PRIMARY KEY `Action`)" );
227 }
228
229 static UINT create_directory_table( MSIHANDLE hdb )
230 {
231 return run_query( hdb, 0,
232 "CREATE TABLE `Directory` ( "
233 "`Directory` CHAR(255) NOT NULL, "
234 "`Directory_Parent` CHAR(255), "
235 "`DefaultDir` CHAR(255) NOT NULL "
236 "PRIMARY KEY `Directory`)" );
237 }
238
239 static UINT create_feature_components_table( MSIHANDLE hdb )
240 {
241 return run_query( hdb, 0,
242 "CREATE TABLE `FeatureComponents` ( "
243 "`Feature_` CHAR(38) NOT NULL, "
244 "`Component_` CHAR(72) NOT NULL "
245 "PRIMARY KEY `Feature_`, `Component_` )" );
246 }
247
248 static UINT create_std_dlls_table( MSIHANDLE hdb )
249 {
250 return run_query( hdb, 0,
251 "CREATE TABLE `StdDlls` ( "
252 "`File` CHAR(255) NOT NULL, "
253 "`Binary_` CHAR(72) NOT NULL "
254 "PRIMARY KEY `File` )" );
255 }
256
257 static UINT create_binary_table( MSIHANDLE hdb )
258 {
259 return run_query( hdb, 0,
260 "CREATE TABLE `Binary` ( "
261 "`Name` CHAR(72) NOT NULL, "
262 "`Data` CHAR(72) NOT NULL "
263 "PRIMARY KEY `Name` )" );
264 }
265
266 #define make_add_entry(type, qtext) \
267 static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
268 { \
269 char insert[] = qtext; \
270 char *query; \
271 UINT sz, r; \
272 sz = strlen(values) + sizeof insert; \
273 query = HeapAlloc(GetProcessHeap(),0,sz); \
274 sprintf(query,insert,values); \
275 r = run_query( hdb, 0, query ); \
276 HeapFree(GetProcessHeap(), 0, query); \
277 return r; \
278 }
279
280 make_add_entry(component,
281 "INSERT INTO `Component` "
282 "(`Component`, `ComponentId`, `Directory_`, "
283 "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
284
285 make_add_entry(custom_action,
286 "INSERT INTO `CustomAction` "
287 "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
288
289 make_add_entry(feature_components,
290 "INSERT INTO `FeatureComponents` "
291 "(`Feature_`, `Component_`) VALUES( %s )")
292
293 make_add_entry(std_dlls,
294 "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
295
296 make_add_entry(binary,
297 "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
298
299 static void test_msiinsert(void)
300 {
301 MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0;
302 UINT r;
303 const char *query;
304 char buf[80];
305 DWORD sz;
306
307 DeleteFileA(msifile);
308
309 /* just MsiOpenDatabase should not create a file */
310 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
311 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
312
313 /* create a table */
314 query = "CREATE TABLE `phone` ( "
315 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
316 "PRIMARY KEY `id`)";
317 r = MsiDatabaseOpenViewA(hdb, query, &hview);
318 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
319 r = MsiViewExecute(hview, 0);
320 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
321 r = MsiViewClose(hview);
322 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
323 r = MsiCloseHandle(hview);
324 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
325
326 query = "SELECT * FROM phone WHERE number = '8675309'";
327 r = MsiDatabaseOpenViewA(hdb, query, &hview2);
328 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
329 r = MsiViewExecute(hview2, 0);
330 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
331 r = MsiViewFetch(hview2, &hrec);
332 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
333
334 /* insert a value into it */
335 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
336 "VALUES('1', 'Abe', '8675309')";
337 r = MsiDatabaseOpenViewA(hdb, query, &hview);
338 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
339 r = MsiViewExecute(hview, 0);
340 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
341 r = MsiViewClose(hview);
342 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
343 r = MsiCloseHandle(hview);
344 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
345
346 r = MsiViewFetch(hview2, &hrec);
347 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
348 r = MsiViewExecute(hview2, 0);
349 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
350 r = MsiViewFetch(hview2, &hrec);
351 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r);
352
353 r = MsiCloseHandle(hrec);
354 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
355 r = MsiViewClose(hview2);
356 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
357 r = MsiCloseHandle(hview2);
358 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
359
360 query = "SELECT * FROM `phone` WHERE `id` = 1";
361 r = do_query(hdb, query, &hrec);
362 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
363
364 /* check the record contains what we put in it */
365 r = MsiRecordGetFieldCount(hrec);
366 ok(r == 3, "record count wrong\n");
367
368 r = MsiRecordIsNull(hrec, 0);
369 ok(r == FALSE, "field 0 not null\n");
370
371 r = MsiRecordGetInteger(hrec, 1);
372 ok(r == 1, "field 1 contents wrong\n");
373 sz = sizeof buf;
374 r = MsiRecordGetStringA(hrec, 2, buf, &sz);
375 ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
376 ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
377 sz = sizeof buf;
378 r = MsiRecordGetStringA(hrec, 3, buf, &sz);
379 ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
380 ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
381
382 r = MsiCloseHandle(hrec);
383 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
384
385 /* open a select query */
386 hrec = 100;
387 query = "SELECT * FROM `phone` WHERE `id` >= 10";
388 r = do_query(hdb, query, &hrec);
389 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
390 ok(hrec == 0, "hrec should be null\n");
391
392 r = MsiCloseHandle(hrec);
393 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
394
395 query = "SELECT * FROM `phone` WHERE `id` < 0";
396 r = do_query(hdb, query, &hrec);
397 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
398
399 query = "SELECT * FROM `phone` WHERE `id` <= 0";
400 r = do_query(hdb, query, &hrec);
401 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
402
403 query = "SELECT * FROM `phone` WHERE `id` <> 1";
404 r = do_query(hdb, query, &hrec);
405 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
406
407 query = "SELECT * FROM `phone` WHERE `id` > 10";
408 r = do_query(hdb, query, &hrec);
409 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
410
411 /* now try a few bad INSERT xqueries */
412 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
413 "VALUES(?, ?)";
414 r = MsiDatabaseOpenViewA(hdb, query, &hview);
415 ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
416
417 /* construct a record to insert */
418 hrec = MsiCreateRecord(4);
419 r = MsiRecordSetInteger(hrec, 1, 2);
420 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
421 r = MsiRecordSetStringA(hrec, 2, "Adam");
422 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
423 r = MsiRecordSetStringA(hrec, 3, "96905305");
424 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
425
426 /* insert another value, using a record and wildcards */
427 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
428 "VALUES(?, ?, ?)";
429 r = MsiDatabaseOpenViewA(hdb, query, &hview);
430 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
431
432 if (r == ERROR_SUCCESS)
433 {
434 r = MsiViewExecute(hview, hrec);
435 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
436 r = MsiViewClose(hview);
437 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
438 r = MsiCloseHandle(hview);
439 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
440 }
441 r = MsiCloseHandle(hrec);
442 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
443
444 r = MsiViewFetch(0, NULL);
445 ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
446
447 r = MsiDatabaseCommit(hdb);
448 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
449
450 r = MsiCloseHandle(hdb);
451 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
452
453 r = DeleteFileA(msifile);
454 ok(r == TRUE, "file didn't exist after commit\n");
455 }
456
457 static void test_msidecomposedesc(void)
458 {
459 UINT (WINAPI *pMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
460 char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
461 const char *desc;
462 UINT r;
463 DWORD len;
464 HMODULE hmod;
465
466 hmod = GetModuleHandleA("msi.dll");
467 pMsiDecomposeDescriptorA = (void*)GetProcAddress(hmod, "MsiDecomposeDescriptorA");
468 if (!pMsiDecomposeDescriptorA)
469 return;
470
471 /* test a valid feature descriptor */
472 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
473 len = 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 /*
490 * Test a valid feature descriptor with the
491 * maximum number of characters and some trailing characters.
492 */
493 desc = "']gAVn-}f(ZXfeAR6.ji"
494 "ThisWillWorkIfTheresLTEThanAGuidsChars>"
495 "3w2x^IGfe?CxI5heAvk."
496 "extra";
497 len = 0;
498 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
499 ok(r == ERROR_SUCCESS, "returned wrong error\n");
500 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
501
502 len = 0;
503 r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
504 ok(r == ERROR_SUCCESS, "returned wrong error\n");
505 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
506
507 len = 0;
508 r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
509 ok(r == ERROR_SUCCESS, "returned wrong error\n");
510 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
511
512 len = 0;
513 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
514 ok(r == ERROR_SUCCESS, "returned wrong error\n");
515 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
516
517 len = 0;
518 r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
519 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
520 ok(len == 0, "length wrong\n");
521
522 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL);
523 ok(r == ERROR_SUCCESS, "returned wrong error\n");
524 }
525
526 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
527 {
528 MSIHANDLE htab = 0;
529 UINT res;
530
531 res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
532 if(res == ERROR_SUCCESS )
533 {
534 UINT r;
535
536 r = MsiViewExecute( htab, hrec );
537 if(r != ERROR_SUCCESS )
538 res = r;
539
540 r = MsiViewClose( htab );
541 if(r != ERROR_SUCCESS )
542 res = r;
543
544 r = MsiCloseHandle( htab );
545 if(r != ERROR_SUCCESS )
546 res = r;
547 }
548 return res;
549 }
550
551 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
552 {
553 return try_query_param( hdb, szQuery, 0 );
554 }
555
556 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
557 {
558 MSIHANDLE hrec = 0;
559 UINT r;
560
561 hrec = MsiCreateRecord( 1 );
562 MsiRecordSetStringA( hrec, 1, "Hello");
563
564 r = try_query_param( hdb, szQuery, hrec );
565
566 MsiCloseHandle( hrec );
567 return r;
568 }
569
570 static void test_msibadqueries(void)
571 {
572 MSIHANDLE hdb = 0;
573 UINT r;
574
575 DeleteFileA(msifile);
576
577 /* just MsiOpenDatabase should not create a file */
578 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
579 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
580
581 r = MsiDatabaseCommit( hdb );
582 ok(r == ERROR_SUCCESS , "Failed to commit database\n");
583
584 r = MsiCloseHandle( hdb );
585 ok(r == ERROR_SUCCESS , "Failed to close database\n");
586
587 /* open it readonly */
588 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb );
589 ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
590
591 /* add a table to it */
592 r = try_query( hdb, "select * from _Tables");
593 ok(r == ERROR_SUCCESS , "query 1 failed\n");
594
595 r = MsiCloseHandle( hdb );
596 ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
597
598 /* open it read/write */
599 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
600 ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
601
602 /* a bunch of test queries that fail with the native MSI */
603
604 r = try_query( hdb, "CREATE TABLE");
605 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
606
607 r = try_query( hdb, "CREATE TABLE `a`");
608 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
609
610 r = try_query( hdb, "CREATE TABLE `a` ()");
611 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
612
613 r = try_query( hdb, "CREATE TABLE `a` (`b`)");
614 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
615
616 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
617 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
618
619 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
620 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
621
622 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
623 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
624
625 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
626 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
627
628 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
629 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
630
631 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
632 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
633
634 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
635 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
636
637 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
638 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
639
640 r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
641 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
642
643 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
644 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
645
646 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
647 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
648
649 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
650 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
651
652 r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
653 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
654
655 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
656 ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
657
658 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
659 ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
660
661 r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
662 "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
663 ok(r == ERROR_SUCCESS , "query 4 failed\n");
664
665 r = MsiDatabaseCommit( hdb );
666 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
667
668 r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
669 "PRIMARY KEY `foo`)");
670 ok(r == ERROR_SUCCESS , "query 4 failed\n");
671
672 r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )");
673 ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
674
675 r = MsiDatabaseCommit( hdb );
676 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
677
678 r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
679 "PRIMARY KEY `ba`)");
680 ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
681
682 r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
683 ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
684
685 r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
686 "PRIMARY KEY `t`)");
687 ok(r == ERROR_SUCCESS , "query 7 failed\n");
688
689 r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
690 ok(r == ERROR_SUCCESS , "query 8 failed\n");
691
692 r = try_query( hdb, "select * from c");
693 ok(r == ERROR_SUCCESS , "query failed\n");
694
695 r = try_query( hdb, "select * from c where b = 'x");
696 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
697
698 r = try_query( hdb, "select * from c where b = 'x'");
699 ok(r == ERROR_SUCCESS, "query failed\n");
700
701 r = try_query( hdb, "select * from 'c'");
702 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
703
704 r = try_query( hdb, "select * from ''");
705 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
706
707 r = try_query( hdb, "select * from c where b = x");
708 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
709
710 r = try_query( hdb, "select * from c where b = \"x\"");
711 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
712
713 r = try_query( hdb, "select * from c where b = 'x'");
714 ok(r == ERROR_SUCCESS, "query failed\n");
715
716 r = try_query( hdb, "select * from c where b = '\"x'");
717 ok(r == ERROR_SUCCESS, "query failed\n");
718
719 if (0) /* FIXME: this query causes trouble with other tests */
720 {
721 r = try_query( hdb, "select * from c where b = '\\\'x'");
722 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
723 }
724
725 r = try_query( hdb, "select * from 'c'");
726 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
727
728 r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`");
729 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
730
731 r = try_query( hdb, "select `c`.b` from `c`");
732 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
733
734 r = try_query( hdb, "select `c`.`b from `c`");
735 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
736
737 r = try_query( hdb, "select `c`.b from `c`");
738 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
739
740 r = try_query( hdb, "select `c.`b` from `c`");
741 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
742
743 r = try_query( hdb, "select c`.`b` from `c`");
744 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
745
746 r = try_query( hdb, "select c.`b` from `c`");
747 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
748
749 r = try_query( hdb, "select `c`.`b` from c`");
750 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
751
752 r = try_query( hdb, "select `c`.`b` from `c");
753 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
754
755 r = try_query( hdb, "select `c`.`b` from c");
756 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
757
758 r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
759 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
760
761 r = try_query( hdb, "SELECT * FROM \5a" );
762 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
763
764 r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
765 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
766
767 r = try_query( hdb, "SELECT * FROM a\5" );
768 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
769
770 r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
771 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
772
773 r = try_query( hdb, "SELECT * FROM -a" );
774 todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
775
776 r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
777 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
778
779 r = try_query( hdb, "SELECT * FROM a-" );
780 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
781
782 r = MsiCloseHandle( hdb );
783 ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
784
785 r = DeleteFileA( msifile );
786 ok(r == TRUE, "file didn't exist after commit\n");
787 }
788
789 static void test_viewmodify(void)
790 {
791 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
792 UINT r;
793 MSIDBERROR err;
794 const char *query;
795 char buffer[0x100];
796 DWORD sz;
797
798 DeleteFileA(msifile);
799
800 /* just MsiOpenDatabase should not create a file */
801 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
802 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
803
804 query = "CREATE TABLE `phone` ( "
805 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
806 "PRIMARY KEY `id`)";
807 r = run_query( hdb, 0, query );
808 ok(r == ERROR_SUCCESS, "query failed\n");
809
810 query = "CREATE TABLE `_Validation` ( "
811 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
812 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
813 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
814 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)";
815 r = run_query( hdb, 0, query );
816 ok(r == ERROR_SUCCESS, "query failed\n");
817
818 query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) "
819 "VALUES('phone', 'id', 'N')";
820 r = run_query( hdb, 0, query );
821 ok(r == ERROR_SUCCESS, "query failed\n");
822
823 /* check what the error function reports without doing anything */
824 sz = 0;
825 /* passing NULL as the 3rd param make function to crash on older platforms */
826 err = MsiViewGetErrorA( 0, NULL, &sz );
827 ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
828
829 /* open a view */
830 query = "SELECT * FROM `phone`";
831 r = MsiDatabaseOpenViewA(hdb, query, &hview);
832 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
833
834 /* see what happens with a good hview and bad args */
835 err = MsiViewGetErrorA( hview, NULL, NULL );
836 ok(err == MSIDBERROR_INVALIDARG || err == MSIDBERROR_NOERROR,
837 "MsiViewGetError returns %u (expected -3)\n", err);
838 err = MsiViewGetErrorA( hview, buffer, NULL );
839 ok(err == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
840
841 /* see what happens with a zero length buffer */
842 sz = 0;
843 buffer[0] = 'x';
844 err = MsiViewGetErrorA( hview, buffer, &sz );
845 ok(err == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
846 ok(buffer[0] == 'x', "buffer cleared\n");
847 ok(sz == 0, "size not zero\n");
848
849 /* ok this one is strange */
850 sz = 0;
851 err = MsiViewGetErrorA( hview, NULL, &sz );
852 ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
853 ok(sz == 0, "size not zero\n");
854
855 /* see if it really has an error */
856 sz = sizeof buffer;
857 buffer[0] = 'x';
858 err = MsiViewGetErrorA( hview, buffer, &sz );
859 ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
860 ok(buffer[0] == 0, "buffer not cleared\n");
861 ok(sz == 0, "size not zero\n");
862
863 r = MsiViewExecute(hview, 0);
864 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
865
866 /* try some invalid records */
867 r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
868 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
869 r = MsiViewModify(hview, -1, 0 );
870 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
871
872 /* try an small record */
873 hrec = MsiCreateRecord(1);
874 r = MsiViewModify(hview, -1, hrec );
875 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
876
877 sz = sizeof buffer;
878 buffer[0] = 'x';
879 err = MsiViewGetErrorA( hview, buffer, &sz );
880 ok(err == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
881 ok(buffer[0] == 0, "buffer not cleared\n");
882 ok(sz == 0, "size not zero\n");
883
884 r = MsiCloseHandle(hrec);
885 ok(r == ERROR_SUCCESS, "failed to close record\n");
886
887 /* insert a valid record */
888 hrec = MsiCreateRecord(3);
889
890 r = MsiRecordSetInteger(hrec, 1, 1);
891 ok(r == ERROR_SUCCESS, "failed to set integer\n");
892 r = MsiRecordSetStringA(hrec, 2, "bob");
893 ok(r == ERROR_SUCCESS, "failed to set string\n");
894 r = MsiRecordSetStringA(hrec, 3, "7654321");
895 ok(r == ERROR_SUCCESS, "failed to set string\n");
896
897 r = MsiViewExecute(hview, 0);
898 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
899 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
900 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
901
902 /* validate it */
903 r = MsiViewExecute(hview, 0);
904 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
905
906 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec );
907 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r);
908
909 sz = sizeof buffer;
910 buffer[0] = 'x';
911 err = MsiViewGetErrorA( hview, buffer, &sz );
912 ok(err == MSIDBERROR_DUPLICATEKEY, "MsiViewGetError returned %u\n", err);
913 ok(!strcmp(buffer, "id"), "expected \"id\" c, got \"%s\"\n", buffer);
914 ok(sz == 2, "size not 2\n");
915
916 /* insert the same thing again */
917 r = MsiViewExecute(hview, 0);
918 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
919
920 /* should fail ... */
921 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
922 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
923
924 /* try to merge the same record */
925 r = MsiViewExecute(hview, 0);
926 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
927 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
928 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
929
930 r = MsiCloseHandle(hrec);
931 ok(r == ERROR_SUCCESS, "failed to close record\n");
932
933 /* try merging a new record */
934 hrec = MsiCreateRecord(3);
935
936 r = MsiRecordSetInteger(hrec, 1, 10);
937 ok(r == ERROR_SUCCESS, "failed to set integer\n");
938 r = MsiRecordSetStringA(hrec, 2, "pepe");
939 ok(r == ERROR_SUCCESS, "failed to set string\n");
940 r = MsiRecordSetStringA(hrec, 3, "7654321");
941 ok(r == ERROR_SUCCESS, "failed to set string\n");
942
943 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
944 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
945 r = MsiViewExecute(hview, 0);
946 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
947
948 r = MsiCloseHandle(hrec);
949 ok(r == ERROR_SUCCESS, "failed to close record\n");
950
951 r = MsiViewClose(hview);
952 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
953 r = MsiCloseHandle(hview);
954 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
955
956 query = "SELECT * FROM `phone`";
957 r = MsiDatabaseOpenViewA(hdb, query, &hview);
958 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
959
960 r = MsiViewExecute(hview, 0);
961 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
962
963 r = MsiViewFetch(hview, &hrec);
964 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
965
966 r = MsiRecordGetInteger(hrec, 1);
967 ok(r == 1, "Expected 1, got %d\n", r);
968
969 sz = sizeof(buffer);
970 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
971 ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
972 ok(!lstrcmpA(buffer, "bob"), "Expected bob, got %s\n", buffer);
973
974 sz = sizeof(buffer);
975 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
976 ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
977 ok(!lstrcmpA(buffer, "7654321"), "Expected 7654321, got %s\n", buffer);
978
979 /* update the view, non-primary key */
980 r = MsiRecordSetStringA(hrec, 3, "3141592");
981 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
982
983 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
984 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
985
986 /* do it again */
987 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
988 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
989
990 /* update the view, primary key */
991 r = MsiRecordSetInteger(hrec, 1, 5);
992 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
993
994 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
995 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
996
997 r = MsiCloseHandle(hrec);
998 ok(r == ERROR_SUCCESS, "failed to close record\n");
999
1000 r = MsiViewClose(hview);
1001 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1002 r = MsiCloseHandle(hview);
1003 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1004
1005 query = "SELECT * FROM `phone`";
1006 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1007 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1008
1009 r = MsiViewExecute(hview, 0);
1010 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1011
1012 r = MsiViewFetch(hview, &hrec);
1013 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1014
1015 r = MsiRecordGetInteger(hrec, 1);
1016 ok(r == 1, "Expected 1, got %d\n", r);
1017
1018 sz = sizeof(buffer);
1019 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
1020 ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1021 ok(!lstrcmpA(buffer, "bob"), "Expected bob, got %s\n", buffer);
1022
1023 sz = sizeof(buffer);
1024 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
1025 ok(r == ERROR_SUCCESS, "MsiRecordGetString failed\n");
1026 ok(!lstrcmpA(buffer, "3141592"), "Expected 3141592, got %s\n", buffer);
1027
1028 r = MsiCloseHandle(hrec);
1029 ok(r == ERROR_SUCCESS, "failed to close record\n");
1030
1031 /* use a record that doesn't come from a view fetch */
1032 hrec = MsiCreateRecord(3);
1033 ok(hrec != 0, "MsiCreateRecord failed\n");
1034
1035 r = MsiRecordSetInteger(hrec, 1, 3);
1036 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1037 r = MsiRecordSetStringA(hrec, 2, "jane");
1038 ok(r == ERROR_SUCCESS, "failed to set string\n");
1039 r = MsiRecordSetStringA(hrec, 3, "112358");
1040 ok(r == ERROR_SUCCESS, "failed to set string\n");
1041
1042 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1043 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
1044
1045 r = MsiCloseHandle(hrec);
1046 ok(r == ERROR_SUCCESS, "failed to close record\n");
1047
1048 /* use a record that doesn't come from a view fetch, primary key matches */
1049 hrec = MsiCreateRecord(3);
1050 ok(hrec != 0, "MsiCreateRecord failed\n");
1051
1052 r = MsiRecordSetInteger(hrec, 1, 1);
1053 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1054 r = MsiRecordSetStringA(hrec, 2, "jane");
1055 ok(r == ERROR_SUCCESS, "failed to set string\n");
1056 r = MsiRecordSetStringA(hrec, 3, "112358");
1057 ok(r == ERROR_SUCCESS, "failed to set string\n");
1058
1059 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1060 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1061
1062 r = MsiCloseHandle(hrec);
1063 ok(r == ERROR_SUCCESS, "failed to close record\n");
1064
1065 hrec = MsiCreateRecord(3);
1066
1067 r = MsiRecordSetInteger(hrec, 1, 2);
1068 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1069 r = MsiRecordSetStringA(hrec, 2, "nick");
1070 ok(r == ERROR_SUCCESS, "failed to set string\n");
1071 r = MsiRecordSetStringA(hrec, 3, "141421");
1072 ok(r == ERROR_SUCCESS, "failed to set string\n");
1073
1074 r = MsiViewExecute(hview, 0);
1075 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1076 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
1077 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1078
1079 r = MsiCloseHandle(hrec);
1080 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1081 r = MsiViewClose(hview);
1082 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1083 r = MsiCloseHandle(hview);
1084 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1085
1086 query = "SELECT * FROM `phone` WHERE `id` = 1";
1087 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1088 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1089 r = MsiViewExecute(hview, 0);
1090 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1091 r = MsiViewFetch(hview, &hrec);
1092 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1093
1094 /* change the id to match the second row */
1095 r = MsiRecordSetInteger(hrec, 1, 2);
1096 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1097 r = MsiRecordSetStringA(hrec, 2, "jerry");
1098 ok(r == ERROR_SUCCESS, "failed to set string\n");
1099
1100 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1101 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1102
1103 r = MsiCloseHandle(hrec);
1104 ok(r == ERROR_SUCCESS, "failed to close record\n");
1105 r = MsiViewClose(hview);
1106 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1107 r = MsiCloseHandle(hview);
1108 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1109
1110 /* broader search */
1111 query = "SELECT * FROM `phone` ORDER BY `id`";
1112 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1113 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1114 r = MsiViewExecute(hview, 0);
1115 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1116 r = MsiViewFetch(hview, &hrec);
1117 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1118
1119 /* change the id to match the second row */
1120 r = MsiRecordSetInteger(hrec, 1, 2);
1121 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1122 r = MsiRecordSetStringA(hrec, 2, "jerry");
1123 ok(r == ERROR_SUCCESS, "failed to set string\n");
1124
1125 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1126 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1127
1128 r = MsiCloseHandle(hrec);
1129 ok(r == ERROR_SUCCESS, "failed to close record\n");
1130 r = MsiViewClose(hview);
1131 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1132 r = MsiCloseHandle(hview);
1133 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1134
1135 r = MsiCloseHandle( hdb );
1136 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1137 }
1138
1139 static MSIHANDLE create_db(void)
1140 {
1141 MSIHANDLE hdb = 0;
1142 UINT res;
1143
1144 DeleteFileW(msifileW);
1145
1146 /* create an empty database */
1147 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1148 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1149 if( res != ERROR_SUCCESS )
1150 return hdb;
1151
1152 res = MsiDatabaseCommit( hdb );
1153 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1154
1155 return hdb;
1156 }
1157
1158 static void test_getcolinfo(void)
1159 {
1160 MSIHANDLE hdb, hview = 0, rec = 0;
1161 UINT r;
1162 DWORD sz;
1163 char buffer[0x20];
1164
1165 /* create an empty db */
1166 hdb = create_db();
1167 ok( hdb, "failed to create db\n");
1168
1169 /* tables should be present */
1170 r = MsiDatabaseOpenViewA(hdb, "select * from _Tables", &hview);
1171 ok( r == ERROR_SUCCESS, "failed to open query\n");
1172
1173 r = MsiViewExecute(hview, 0);
1174 ok( r == ERROR_SUCCESS, "failed to execute query\n");
1175
1176 /* check that NAMES works */
1177 rec = 0;
1178 r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1179 ok( r == ERROR_SUCCESS, "failed to get names\n");
1180 sz = sizeof buffer;
1181 r = MsiRecordGetStringA(rec, 1, buffer, &sz );
1182 ok( r == ERROR_SUCCESS, "failed to get string\n");
1183 ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
1184 r = MsiCloseHandle( rec );
1185 ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1186
1187 /* check that TYPES works */
1188 rec = 0;
1189 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1190 ok( r == ERROR_SUCCESS, "failed to get names\n");
1191 sz = sizeof buffer;
1192 r = MsiRecordGetStringA(rec, 1, buffer, &sz );
1193 ok( r == ERROR_SUCCESS, "failed to get string\n");
1194 ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
1195 r = MsiCloseHandle( rec );
1196 ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1197
1198 /* check that invalid values fail */
1199 rec = 0;
1200 r = MsiViewGetColumnInfo( hview, 100, &rec );
1201 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1202 ok( rec == 0, "returned a record\n");
1203
1204 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1205 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1206
1207 r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1208 ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1209
1210 r = MsiViewClose(hview);
1211 ok( r == ERROR_SUCCESS, "failed to close view\n");
1212 r = MsiCloseHandle(hview);
1213 ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1214 r = MsiCloseHandle(hdb);
1215 ok( r == ERROR_SUCCESS, "failed to close database\n");
1216 }
1217
1218 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1219 {
1220 MSIHANDLE hview = 0, rec = 0;
1221 UINT r;
1222
1223 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1224 if( r != ERROR_SUCCESS )
1225 return r;
1226
1227 r = MsiViewExecute(hview, 0);
1228 if( r == ERROR_SUCCESS )
1229 {
1230 MsiViewGetColumnInfo( hview, type, &rec );
1231 }
1232 MsiViewClose(hview);
1233 MsiCloseHandle(hview);
1234 return rec;
1235 }
1236
1237 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1238 {
1239 MSIHANDLE hview = 0, rec = 0;
1240 UINT r, type = 0;
1241 char query[0x100];
1242
1243 sprintf(query, "select * from `_Columns` where `Table` = '%s'", table );
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 while (1)
1253 {
1254 r = MsiViewFetch( hview, &rec );
1255 if( r != ERROR_SUCCESS)
1256 break;
1257 r = MsiRecordGetInteger( rec, 2 );
1258 if (r == field)
1259 type = MsiRecordGetInteger( rec, 4 );
1260 MsiCloseHandle( rec );
1261 }
1262 }
1263 MsiViewClose(hview);
1264 MsiCloseHandle(hview);
1265 return type;
1266 }
1267
1268 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
1269 {
1270 CHAR buffer[0x20];
1271 UINT r;
1272 DWORD sz;
1273
1274 sz = sizeof buffer;
1275 r = MsiRecordGetStringA( rec, field, buffer, &sz );
1276 return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1277 }
1278
1279 static void test_viewgetcolumninfo(void)
1280 {
1281 MSIHANDLE hdb = 0, rec;
1282 UINT r;
1283
1284 hdb = create_db();
1285 ok( hdb, "failed to create db\n");
1286
1287 r = run_query( hdb, 0,
1288 "CREATE TABLE `Properties` "
1289 "( `Property` CHAR(255), "
1290 " `Value` CHAR(1), "
1291 " `Intvalue` INT, "
1292 " `Integervalue` INTEGER, "
1293 " `Shortvalue` SHORT, "
1294 " `Longvalue` LONG, "
1295 " `Longcharvalue` LONGCHAR "
1296 " PRIMARY KEY `Property`)" );
1297 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1298
1299 /* check the column types */
1300 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1301 ok( rec, "failed to get column info record\n" );
1302
1303 ok( check_record( rec, 1, "S255"), "wrong record type\n");
1304 ok( check_record( rec, 2, "S1"), "wrong record type\n");
1305 ok( check_record( rec, 3, "I2"), "wrong record type\n");
1306 ok( check_record( rec, 4, "I2"), "wrong record type\n");
1307 ok( check_record( rec, 5, "I2"), "wrong record type\n");
1308 ok( check_record( rec, 6, "I4"), "wrong record type\n");
1309 ok( check_record( rec, 7, "S0"), "wrong record type\n");
1310
1311 MsiCloseHandle( rec );
1312
1313 /* check the type in _Columns */
1314 ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1315 ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1316 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1317 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1318 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1319 ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1320 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1321
1322 /* now try the names */
1323 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1324 ok( rec, "failed to get column info record\n" );
1325
1326 ok( check_record( rec, 1, "Property"), "wrong record type\n");
1327 ok( check_record( rec, 2, "Value"), "wrong record type\n");
1328 ok( check_record( rec, 3, "Intvalue"), "wrong record type\n");
1329 ok( check_record( rec, 4, "Integervalue"), "wrong record type\n");
1330 ok( check_record( rec, 5, "Shortvalue"), "wrong record type\n");
1331 ok( check_record( rec, 6, "Longvalue"), "wrong record type\n");
1332 ok( check_record( rec, 7, "Longcharvalue"), "wrong record type\n");
1333
1334 MsiCloseHandle( rec );
1335
1336 r = run_query( hdb, 0,
1337 "CREATE TABLE `Binary` "
1338 "( `Name` CHAR(255), `Data` OBJECT PRIMARY KEY `Name`)" );
1339 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1340
1341 /* check the column types */
1342 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1343 ok( rec, "failed to get column info record\n" );
1344
1345 ok( check_record( rec, 1, "S255"), "wrong record type\n");
1346 ok( check_record( rec, 2, "V0"), "wrong record type\n");
1347
1348 MsiCloseHandle( rec );
1349
1350 /* check the type in _Columns */
1351 ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1352 ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1353
1354 /* now try the names */
1355 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1356 ok( rec, "failed to get column info record\n" );
1357
1358 ok( check_record( rec, 1, "Name"), "wrong record type\n");
1359 ok( check_record( rec, 2, "Data"), "wrong record type\n");
1360 MsiCloseHandle( rec );
1361
1362 r = run_query( hdb, 0,
1363 "CREATE TABLE `UIText` "
1364 "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1365 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1366
1367 ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1368 ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1369
1370 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1371 ok( rec, "failed to get column info record\n" );
1372 ok( check_record( rec, 1, "Key"), "wrong record type\n");
1373 ok( check_record( rec, 2, "Text"), "wrong record type\n");
1374 MsiCloseHandle( rec );
1375
1376 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1377 ok( rec, "failed to get column info record\n" );
1378 ok( check_record( rec, 1, "s72"), "wrong record type\n");
1379 ok( check_record( rec, 2, "L255"), "wrong record type\n");
1380 MsiCloseHandle( rec );
1381
1382 MsiCloseHandle( hdb );
1383 }
1384
1385 static void test_msiexport(void)
1386 {
1387 MSIHANDLE hdb = 0, hview = 0;
1388 UINT r;
1389 const char *query;
1390 char path[MAX_PATH];
1391 const char file[] = "phone.txt";
1392 HANDLE handle;
1393 char buffer[0x100];
1394 DWORD length;
1395 const char expected[] =
1396 "id\tname\tnumber\r\n"
1397 "I2\tS32\tS32\r\n"
1398 "phone\tid\r\n"
1399 "1\tAbe\t8675309\r\n";
1400
1401 DeleteFileW(msifileW);
1402
1403 /* just MsiOpenDatabase should not create a file */
1404 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1405 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1406
1407 /* create a table */
1408 query = "CREATE TABLE `phone` ( "
1409 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1410 "PRIMARY KEY `id`)";
1411 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1412 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1413 r = MsiViewExecute(hview, 0);
1414 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1415 r = MsiViewClose(hview);
1416 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1417 r = MsiCloseHandle(hview);
1418 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1419
1420 /* insert a value into it */
1421 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1422 "VALUES('1', 'Abe', '8675309')";
1423 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1424 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1425 r = MsiViewExecute(hview, 0);
1426 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1427 r = MsiViewClose(hview);
1428 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1429 r = MsiCloseHandle(hview);
1430 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1431
1432 GetCurrentDirectoryA(MAX_PATH, path);
1433
1434 r = MsiDatabaseExportA(hdb, "phone", path, file);
1435 ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1436
1437 MsiCloseHandle(hdb);
1438
1439 lstrcatA(path, "\\");
1440 lstrcatA(path, file);
1441
1442 /* check the data that was written */
1443 length = 0;
1444 memset(buffer, 0, sizeof buffer);
1445 handle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1446 if (handle != INVALID_HANDLE_VALUE)
1447 {
1448 ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1449 CloseHandle(handle);
1450 DeleteFileA(path);
1451 }
1452 else
1453 ok(0, "failed to open file %s\n", path);
1454
1455 ok( length == strlen(expected), "length of data wrong\n");
1456 ok( !lstrcmpA(buffer, expected), "data doesn't match\n");
1457 DeleteFileA(msifile);
1458 }
1459
1460 static void test_longstrings(void)
1461 {
1462 const char insert_query[] =
1463 "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1464 char *str;
1465 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1466 DWORD len;
1467 UINT r;
1468 const DWORD STRING_LENGTH = 0x10005;
1469
1470 DeleteFileW(msifileW);
1471 /* just MsiOpenDatabase should not create a file */
1472 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1473 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1474
1475 /* create a table */
1476 r = try_query( hdb,
1477 "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1478 ok(r == ERROR_SUCCESS, "query failed\n");
1479
1480 /* try to insert a very long string */
1481 str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
1482 len = strchr(insert_query, 'Z') - insert_query;
1483 strcpy(str, insert_query);
1484 memset(str+len, 'Z', STRING_LENGTH);
1485 strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1486 r = try_query( hdb, str );
1487 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1488
1489 HeapFree(GetProcessHeap(), 0, str);
1490
1491 r = MsiDatabaseCommit(hdb);
1492 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1493 MsiCloseHandle(hdb);
1494
1495 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
1496 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1497
1498 r = MsiDatabaseOpenViewA(hdb, "select * from `strings` where `id` = 1", &hview);
1499 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1500
1501 r = MsiViewExecute(hview, 0);
1502 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1503
1504 r = MsiViewFetch(hview, &hrec);
1505 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1506
1507 MsiViewClose(hview);
1508 MsiCloseHandle(hview);
1509
1510 r = MsiRecordGetStringA(hrec, 2, NULL, &len);
1511 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1512 ok(len == STRING_LENGTH, "string length wrong\n");
1513
1514 MsiCloseHandle(hrec);
1515 MsiCloseHandle(hdb);
1516 DeleteFileA(msifile);
1517 }
1518
1519 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1520 {
1521 HANDLE file;
1522 DWORD written;
1523
1524 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1525 if (file == INVALID_HANDLE_VALUE)
1526 return;
1527
1528 WriteFile(file, data, strlen(data), &written, NULL);
1529 WriteFile(file, "\n", strlen("\n"), &written, NULL);
1530
1531 if (size)
1532 {
1533 SetFilePointer(file, size, NULL, FILE_BEGIN);
1534 SetEndOfFile(file);
1535 }
1536
1537 CloseHandle(file);
1538 }
1539
1540 #define create_file(name) create_file_data(name, name, 0)
1541
1542 static void test_streamtable(void)
1543 {
1544 MSIHANDLE hdb = 0, rec, view, hsi;
1545 char file[MAX_PATH];
1546 char buf[MAX_PATH];
1547 DWORD size;
1548 UINT r;
1549
1550 hdb = create_db();
1551 ok( hdb, "failed to create db\n");
1552
1553 r = run_query( hdb, 0,
1554 "CREATE TABLE `Properties` "
1555 "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" );
1556 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1557
1558 r = run_query( hdb, 0,
1559 "INSERT INTO `Properties` "
1560 "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1561 ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1562
1563 r = MsiDatabaseCommit( hdb );
1564 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1565
1566 MsiCloseHandle( hdb );
1567
1568 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
1569 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1570
1571 /* check the column types */
1572 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1573 ok( rec, "failed to get column info record\n" );
1574
1575 ok( check_record( rec, 1, "s62"), "wrong record type\n");
1576 ok( check_record( rec, 2, "V0"), "wrong record type\n");
1577
1578 MsiCloseHandle( rec );
1579
1580 /* now try the names */
1581 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1582 ok( rec, "failed to get column info record\n" );
1583
1584 ok( check_record( rec, 1, "Name"), "wrong record type\n");
1585 ok( check_record( rec, 2, "Data"), "wrong record type\n");
1586
1587 MsiCloseHandle( rec );
1588
1589 r = MsiDatabaseOpenViewA( hdb,
1590 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1591 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1592
1593 r = MsiViewExecute( view, 0 );
1594 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1595
1596 r = MsiViewFetch( view, &rec );
1597 ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1598
1599 MsiCloseHandle( rec );
1600 MsiViewClose( view );
1601 MsiCloseHandle( view );
1602
1603 /* create a summary information stream */
1604 r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1605 ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1606
1607 r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1608 ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1609
1610 r = MsiSummaryInfoPersist( hsi );
1611 ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1612
1613 MsiCloseHandle( hsi );
1614
1615 r = MsiDatabaseOpenViewA( hdb,
1616 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1617 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1618
1619 r = MsiViewExecute( view, 0 );
1620 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1621
1622 r = MsiViewFetch( view, &rec );
1623 ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1624
1625 MsiCloseHandle( rec );
1626 MsiViewClose( view );
1627 MsiCloseHandle( view );
1628
1629 /* insert a file into the _Streams table */
1630 create_file( "test.txt" );
1631
1632 rec = MsiCreateRecord( 2 );
1633 MsiRecordSetStringA( rec, 1, "data" );
1634
1635 r = MsiRecordSetStreamA( rec, 2, "test.txt" );
1636 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1637
1638 DeleteFileA("test.txt");
1639
1640 r = MsiDatabaseOpenViewA( hdb,
1641 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1642 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1643
1644 r = MsiViewExecute( view, rec );
1645 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1646
1647 MsiCloseHandle( rec );
1648 MsiViewClose( view );
1649 MsiCloseHandle( view );
1650
1651 /* insert another one */
1652 create_file( "test1.txt" );
1653
1654 rec = MsiCreateRecord( 2 );
1655 MsiRecordSetStringA( rec, 1, "data1" );
1656
1657 r = MsiRecordSetStreamA( rec, 2, "test1.txt" );
1658 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1659
1660 DeleteFileA("test1.txt");
1661
1662 r = MsiDatabaseOpenViewA( hdb,
1663 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1664 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1665
1666 r = MsiViewExecute( view, rec );
1667 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1668
1669 MsiCloseHandle( rec );
1670 MsiViewClose( view );
1671 MsiCloseHandle( view );
1672
1673 r = MsiDatabaseOpenViewA( hdb,
1674 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1675 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1676
1677 r = MsiViewExecute( view, 0 );
1678 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1679
1680 r = MsiViewFetch( view, &rec );
1681 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1682
1683 size = MAX_PATH;
1684 r = MsiRecordGetStringA( rec, 1, file, &size );
1685 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1686 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file);
1687
1688 size = MAX_PATH;
1689 memset(buf, 0, MAX_PATH);
1690 r = MsiRecordReadStream( rec, 2, buf, &size );
1691 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1692 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf);
1693
1694 MsiCloseHandle( rec );
1695 MsiViewClose( view );
1696 MsiCloseHandle( view );
1697
1698 r = MsiDatabaseOpenViewA( hdb,
1699 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1700 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1701
1702 r = MsiViewExecute( view, 0 );
1703 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1704
1705 r = MsiViewFetch( view, &rec );
1706 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1707
1708 size = MAX_PATH;
1709 r = MsiRecordGetStringA( rec, 1, file, &size );
1710 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1711 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file);
1712
1713 size = MAX_PATH;
1714 memset(buf, 0, MAX_PATH);
1715 r = MsiRecordReadStream( rec, 2, buf, &size );
1716 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1717 ok( !lstrcmpA(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf);
1718
1719 MsiCloseHandle( rec );
1720 MsiViewClose( view );
1721 MsiCloseHandle( view );
1722
1723 /* perform an update */
1724 create_file( "test2.txt" );
1725 rec = MsiCreateRecord( 1 );
1726
1727 r = MsiRecordSetStreamA( rec, 1, "test2.txt" );
1728 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1729
1730 DeleteFileA("test2.txt");
1731
1732 r = MsiDatabaseOpenViewA( hdb,
1733 "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1734 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1735
1736 r = MsiViewExecute( view, rec );
1737 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1738
1739 MsiCloseHandle( rec );
1740 MsiViewClose( view );
1741 MsiCloseHandle( view );
1742
1743 r = MsiDatabaseOpenViewA( hdb,
1744 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1745 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1746
1747 r = MsiViewExecute( view, 0 );
1748 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1749
1750 r = MsiViewFetch( view, &rec );
1751 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1752
1753 size = MAX_PATH;
1754 r = MsiRecordGetStringA( rec, 1, file, &size );
1755 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1756 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file);
1757
1758 size = MAX_PATH;
1759 memset(buf, 0, MAX_PATH);
1760 r = MsiRecordReadStream( rec, 2, buf, &size );
1761 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1762 todo_wine ok( !lstrcmpA(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf);
1763
1764 MsiCloseHandle( rec );
1765 MsiViewClose( view );
1766 MsiCloseHandle( view );
1767 MsiCloseHandle( hdb );
1768 DeleteFileA(msifile);
1769 }
1770
1771 static void test_binary(void)
1772 {
1773 MSIHANDLE hdb = 0, rec;
1774 char file[MAX_PATH];
1775 char buf[MAX_PATH];
1776 DWORD size;
1777 LPCSTR query;
1778 UINT r;
1779
1780 /* insert a file into the Binary table */
1781 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1782 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1783
1784 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)";
1785 r = run_query( hdb, 0, query );
1786 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1787
1788 create_file( "test.txt" );
1789 rec = MsiCreateRecord( 1 );
1790 r = MsiRecordSetStreamA( rec, 1, "test.txt" );
1791 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1792 DeleteFileA( "test.txt" );
1793
1794 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1795 r = run_query( hdb, rec, query );
1796 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1797
1798 r = MsiCloseHandle( rec );
1799 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1800
1801 r = MsiDatabaseCommit( hdb );
1802 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1803
1804 r = MsiCloseHandle( hdb );
1805 ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1806
1807 /* read file from the Stream table */
1808 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb );
1809 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1810
1811 query = "SELECT * FROM `_Streams`";
1812 r = do_query( hdb, query, &rec );
1813 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1814
1815 size = MAX_PATH;
1816 r = MsiRecordGetStringA( rec, 1, file, &size );
1817 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1818 ok( !lstrcmpA(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1819
1820 size = MAX_PATH;
1821 memset( buf, 0, MAX_PATH );
1822 r = MsiRecordReadStream( rec, 2, buf, &size );
1823 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1824 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1825
1826 r = MsiCloseHandle( rec );
1827 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1828
1829 /* read file from the Binary table */
1830 query = "SELECT * FROM `Binary`";
1831 r = do_query( hdb, query, &rec );
1832 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1833
1834 size = MAX_PATH;
1835 r = MsiRecordGetStringA( rec, 1, file, &size );
1836 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1837 ok( !lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file );
1838
1839 size = MAX_PATH;
1840 memset( buf, 0, MAX_PATH );
1841 r = MsiRecordReadStream( rec, 3, buf, &size );
1842 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1843 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf );
1844
1845 r = MsiCloseHandle( rec );
1846 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1847
1848 r = MsiCloseHandle( hdb );
1849 ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1850
1851 DeleteFileA( msifile );
1852 }
1853
1854 static void test_where_not_in_selected(void)
1855 {
1856 MSIHANDLE hdb = 0, rec, view;
1857 LPCSTR query;
1858 UINT r;
1859
1860 hdb = create_db();
1861 ok( hdb, "failed to create db\n");
1862
1863 r = run_query(hdb, 0,
1864 "CREATE TABLE `IESTable` ("
1865 "`Action` CHAR(64), "
1866 "`Condition` CHAR(64), "
1867 "`Sequence` LONG PRIMARY KEY `Sequence`)");
1868 ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1869
1870 r = run_query(hdb, 0,
1871 "CREATE TABLE `CATable` ("
1872 "`Action` CHAR(64), "
1873 "`Type` LONG PRIMARY KEY `Type`)");
1874 ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1875
1876 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1877 "( `Action`, `Condition`, `Sequence`) "
1878 "VALUES ( 'clean', 'cond4', 4)");
1879 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1880
1881 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1882 "( `Action`, `Condition`, `Sequence`) "
1883 "VALUES ( 'depends', 'cond1', 1)");
1884 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1885
1886 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1887 "( `Action`, `Condition`, `Sequence`) "
1888 "VALUES ( 'build', 'cond2', 2)");
1889 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1890
1891 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1892 "( `Action`, `Condition`, `Sequence`) "
1893 "VALUES ( 'build2', 'cond6', 6)");
1894 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1895
1896 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1897 "( `Action`, `Condition`, `Sequence`) "
1898 "VALUES ( 'build', 'cond3', 3)");
1899 ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1900
1901 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1902 "( `Action`, `Type` ) "
1903 "VALUES ( 'build', 32)");
1904 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1905
1906 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1907 "( `Action`, `Type` ) "
1908 "VALUES ( 'depends', 64)");
1909 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1910
1911 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1912 "( `Action`, `Type` ) "
1913 "VALUES ( 'clean', 63)");
1914 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1915
1916 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1917 "( `Action`, `Type` ) "
1918 "VALUES ( 'build2', 34)");
1919 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1920 query = "Select IESTable.Condition from CATable, IESTable where "
1921 "CATable.Action = IESTable.Action and CATable.Type = 32";
1922 r = MsiDatabaseOpenViewA(hdb, query, &view);
1923 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1924
1925 r = MsiViewExecute(view, 0);
1926 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
1927
1928 r = MsiViewFetch(view, &rec);
1929 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1930
1931 ok( check_record( rec, 1, "cond2"), "wrong condition\n");
1932
1933 MsiCloseHandle( rec );
1934 r = MsiViewFetch(view, &rec);
1935 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
1936
1937 ok( check_record( rec, 1, "cond3"), "wrong condition\n");
1938
1939 MsiCloseHandle( rec );
1940 MsiViewClose(view);
1941 MsiCloseHandle(view);
1942
1943 MsiCloseHandle( hdb );
1944 DeleteFileA(msifile);
1945 }
1946
1947
1948 static void test_where(void)
1949 {
1950 MSIHANDLE hdb = 0, rec, view;
1951 LPCSTR query;
1952 UINT r;
1953 DWORD size;
1954 CHAR buf[MAX_PATH];
1955 UINT count;
1956
1957 hdb = create_db();
1958 ok( hdb, "failed to create db\n");
1959
1960 r = run_query( hdb, 0,
1961 "CREATE TABLE `Media` ("
1962 "`DiskId` SHORT NOT NULL, "
1963 "`LastSequence` LONG, "
1964 "`DiskPrompt` CHAR(64) LOCALIZABLE, "
1965 "`Cabinet` CHAR(255), "
1966 "`VolumeLabel` CHAR(32), "
1967 "`Source` CHAR(72) "
1968 "PRIMARY KEY `DiskId`)" );
1969 ok( r == S_OK, "cannot create Media table: %d\n", r );
1970
1971 r = run_query( hdb, 0, "INSERT INTO `Media` "
1972 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1973 "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
1974 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1975
1976 r = run_query( hdb, 0, "INSERT INTO `Media` "
1977 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1978 "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
1979 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1980
1981 r = run_query( hdb, 0, "INSERT INTO `Media` "
1982 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1983 "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
1984 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1985
1986 query = "SELECT * FROM `Media`";
1987 r = do_query(hdb, query, &rec);
1988 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1989 ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
1990 MsiCloseHandle( rec );
1991
1992 query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
1993 r = do_query(hdb, query, &rec);
1994 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1995 ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
1996
1997 r = MsiRecordGetInteger(rec, 1);
1998 ok( 2 == r, "field wrong\n");
1999 r = MsiRecordGetInteger(rec, 2);
2000 ok( 1 == r, "field wrong\n");
2001 MsiCloseHandle( rec );
2002
2003 query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
2004 r = MsiDatabaseOpenViewA(hdb, query, &view);
2005 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
2006
2007 r = MsiViewExecute(view, 0);
2008 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
2009
2010 r = MsiViewFetch(view, &rec);
2011 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2012
2013 count = MsiRecordGetFieldCount( rec );
2014 ok( count == 1, "Expected 1 record fields, got %d\n", count );
2015
2016 size = MAX_PATH;
2017 r = MsiRecordGetStringA( rec, 1, buf, &size );
2018 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2019 ok( !lstrcmpA( buf, "2" ), "For (row %d, column 1) expected '%d', got %s\n", 0, 2, buf );
2020 MsiCloseHandle( rec );
2021
2022 r = MsiViewFetch(view, &rec);
2023 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2024
2025 size = MAX_PATH;
2026 r = MsiRecordGetStringA( rec, 1, buf, &size );
2027 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
2028 ok( !lstrcmpA( buf, "3" ), "For (row %d, column 1) expected '%d', got %s\n", 1, 3, buf );
2029 MsiCloseHandle( rec );
2030
2031 r = MsiViewFetch(view, &rec);
2032 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
2033
2034 MsiViewClose(view);
2035 MsiCloseHandle(view);
2036
2037 MsiCloseHandle( rec );
2038
2039 rec = 0;
2040 query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
2041 r = do_query(hdb, query, &rec);
2042 ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2043 MsiCloseHandle( rec );
2044
2045 rec = 0;
2046 query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
2047 r = do_query(hdb, query, &rec);
2048 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2049 MsiCloseHandle( rec );
2050
2051 rec = 0;
2052 query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
2053 r = do_query(hdb, query, &rec);
2054 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2055 MsiCloseHandle( rec );
2056
2057 rec = 0;
2058 query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
2059 r = do_query(hdb, query, &rec);
2060 ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2061 MsiCloseHandle( rec );
2062
2063 rec = 0;
2064 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
2065 r = do_query(hdb, query, &rec);
2066 ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
2067 MsiCloseHandle( rec );
2068
2069 rec = MsiCreateRecord(1);
2070 MsiRecordSetStringA(rec, 1, "");
2071
2072 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
2073 r = MsiDatabaseOpenViewA(hdb, query, &view);
2074 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2075 r = MsiViewExecute(view, rec);
2076 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2077
2078 MsiCloseHandle(rec);
2079
2080 r = MsiViewFetch(view, &rec);
2081 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2082
2083 MsiCloseHandle(rec);
2084 MsiViewClose(view);
2085 MsiCloseHandle(view);
2086
2087 MsiCloseHandle( hdb );
2088 DeleteFileA(msifile);
2089 }
2090
2091 static CHAR CURR_DIR[MAX_PATH];
2092
2093 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
2094 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
2095 "TestTable\tFirstPrimaryColumn\n"
2096 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
2097
2098 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
2099 "s255\ts255\n"
2100 "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
2101 "papaya\tleaf\n"
2102 "papaya\tflower\n";
2103
2104 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
2105 "s72\ts72\ts72\ts72\ts72\ts72\n"
2106 "Table\tA\r\n"
2107 "a\tb\tc\td\te\tf\n"
2108 "g\th\ti\t\rj\tk\tl\r\n";
2109
2110 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
2111 "s72\ts72\ts72\ts72\ts72\ts72\n"
2112 "Table2\tA\r\n"
2113 "a\tb\tc\td\te\tf\n"
2114 "g\th\ti\tj\tk\tl\r\n";
2115
2116 static const CHAR suminfo[] = "PropertyId\tValue\n"
2117 "i2\tl255\n"
2118 "_SummaryInformation\tPropertyId\n"
2119 "1\t1252\n"
2120 "2\tInstaller Database\n"
2121 "3\tInstaller description\n"
2122 "4\tWineHQ\n"
2123 "5\tInstaller\n"
2124 "6\tInstaller comments\n"
2125 "7\tIntel;1033,2057\n"
2126 "9\t{12345678-1234-1234-1234-123456789012}\n"
2127 "12\t2009/04/12 15:46:11\n"
2128 "13\t2009/04/12 15:46:11\n"
2129 "14\t200\n"
2130 "15\t2\n"
2131 "18\tVim\n"
2132 "19\t2\n";
2133
2134 static void write_file(const CHAR *filename, const char *data, int data_size)
2135 {
2136 DWORD size;
2137
2138 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
2139 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2140 WriteFile(hf, data, data_size, &size, NULL);
2141 CloseHandle(hf);
2142 }
2143
2144 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2145 {
2146 UINT r;
2147
2148 write_file("temp_file", table_data, (lstrlenA(table_data) - 1) * sizeof(char));
2149 r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2150 DeleteFileA("temp_file");
2151
2152 return r;
2153 }
2154
2155 static void test_suminfo_import(void)
2156 {
2157 MSIHANDLE hdb, hsi, view = 0;
2158 LPCSTR query;
2159 UINT r, count, size, type;
2160 char str_value[50];
2161 INT int_value;
2162 FILETIME ft_value;
2163
2164 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2165
2166 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2167 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2168
2169 r = add_table_to_db(hdb, suminfo);
2170 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2171
2172 /* _SummaryInformation is not imported as a regular table... */
2173
2174 query = "SELECT * FROM `_SummaryInformation`";
2175 r = MsiDatabaseOpenViewA(hdb, query, &view);
2176 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2177 MsiCloseHandle(view);
2178
2179 /* ...its data is added to the special summary information stream */
2180
2181 r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2182 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2183
2184 r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2185 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2186 ok(count == 14, "Expected 14, got %u\n", count);
2187
2188 r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2189 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2190 ok(type == VT_I2, "Expected VT_I2, got %u\n", type);
2191 ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2192
2193 size = sizeof(str_value);
2194 r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2195 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2196 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2197 ok(size == 18, "Expected 18, got %u\n", size);
2198 ok(!strcmp(str_value, "Installer Database"),
2199 "Expected \"Installer Database\", got %s\n", str_value);
2200
2201 size = sizeof(str_value);
2202 r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2203 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2204 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2205 ok(!strcmp(str_value, "Installer description"),
2206 "Expected \"Installer description\", got %s\n", str_value);
2207
2208 size = sizeof(str_value);
2209 r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2210 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2211 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2212 ok(!strcmp(str_value, "WineHQ"),
2213 "Expected \"WineHQ\", got %s\n", str_value);
2214
2215 size = sizeof(str_value);
2216 r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2217 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2218 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2219 ok(!strcmp(str_value, "Installer"),
2220 "Expected \"Installer\", got %s\n", str_value);
2221
2222 size = sizeof(str_value);
2223 r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2224 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2225 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2226 ok(!strcmp(str_value, "Installer comments"),
2227 "Expected \"Installer comments\", got %s\n", str_value);
2228
2229 size = sizeof(str_value);
2230 r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2231 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2232 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2233 ok(!strcmp(str_value, "Intel;1033,2057"),
2234 "Expected \"Intel;1033,2057\", got %s\n", str_value);
2235
2236 size = sizeof(str_value);
2237 r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2239 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2240 ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2241 "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2242
2243 r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2244 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2245 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2246
2247 r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2248 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2249 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2250
2251 r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2252 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2253 ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
2254 ok(int_value == 200, "Expected 200, got %d\n", int_value);
2255
2256 r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2257 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2258 ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
2259 ok(int_value == 2, "Expected 2, got %d\n", int_value);
2260
2261 r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2262 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2263 ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
2264 ok(int_value == 2, "Expected 2, got %d\n", int_value);
2265
2266 size = sizeof(str_value);
2267 r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2269 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2270 ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2271
2272 MsiCloseHandle(hsi);
2273 MsiCloseHandle(hdb);
2274 DeleteFileA(msifile);
2275 }
2276
2277 static void test_msiimport(void)
2278 {
2279 MSIHANDLE hdb, view, rec;
2280 LPCSTR query;
2281 UINT r, count;
2282 signed int i;
2283
2284 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2285
2286 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2287 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2288
2289 r = add_table_to_db(hdb, test_data);
2290 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2291
2292 r = add_table_to_db(hdb, two_primary);
2293 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2294
2295 r = add_table_to_db(hdb, endlines1);
2296 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2297
2298 r = add_table_to_db(hdb, endlines2);
2299 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2300
2301 query = "SELECT * FROM `TestTable`";
2302 r = MsiDatabaseOpenViewA(hdb, query, &view);
2303 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2304
2305 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2307 count = MsiRecordGetFieldCount(rec);
2308 ok(count == 9, "Expected 9, got %d\n", count);
2309 ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
2310 ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
2311 ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
2312 ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
2313 ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
2314 ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
2315 ok(check_record(rec, 7, "String"), "Expected String\n");
2316 ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
2317 ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
2318 MsiCloseHandle(rec);
2319
2320 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2322 count = MsiRecordGetFieldCount(rec);
2323 ok(count == 9, "Expected 9, got %d\n", count);
2324 ok(check_record(rec, 1, "s255"), "Expected s255\n");
2325 ok(check_record(rec, 2, "i2"), "Expected i2\n");
2326 ok(check_record(rec, 3, "i2"), "Expected i2\n");
2327 ok(check_record(rec, 4, "I2"), "Expected I2\n");
2328 ok(check_record(rec, 5, "i4"), "Expected i4\n");
2329 ok(check_record(rec, 6, "I4"), "Expected I4\n");
2330 ok(check_record(rec, 7, "S255"), "Expected S255\n");
2331 ok(check_record(rec, 8, "S0"), "Expected S0\n");
2332 ok(check_record(rec, 9, "s0"), "Expected s0\n");
2333 MsiCloseHandle(rec);
2334
2335 query = "SELECT * FROM `TestTable`";
2336 r = do_query(hdb, query, &rec);
2337 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2338 ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
2339 ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
2340 ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
2341 ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
2342
2343 i = MsiRecordGetInteger(rec, 2);
2344 ok(i == 5, "Expected 5, got %d\n", i);
2345
2346 i = MsiRecordGetInteger(rec, 3);
2347 ok(i == 2, "Expected 2, got %d\n", i);
2348
2349 i = MsiRecordGetInteger(rec, 4);
2350 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
2351
2352 i = MsiRecordGetInteger(rec, 5);
2353 ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
2354
2355 i = MsiRecordGetInteger(rec, 6);
2356 ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
2357
2358 MsiCloseHandle(rec);
2359 MsiViewClose(view);
2360 MsiCloseHandle(view);
2361
2362 query = "SELECT * FROM `TwoPrimary`";
2363 r = MsiDatabaseOpenViewA(hdb, query, &view);
2364 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2365
2366 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2367 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2368 count = MsiRecordGetFieldCount(rec);
2369 ok(count == 2, "Expected 2, got %d\n", count);
2370 ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
2371 ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
2372
2373 MsiCloseHandle(rec);
2374
2375 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2376 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2377 count = MsiRecordGetFieldCount(rec);
2378 ok(count == 2, "Expected 2, got %d\n", count);
2379 ok(check_record(rec, 1, "s255"), "Expected s255\n");
2380 ok(check_record(rec, 2, "s255"), "Expected s255\n");
2381 MsiCloseHandle(rec);
2382
2383 r = MsiViewExecute(view, 0);
2384 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2385
2386 r = MsiViewFetch(view, &rec);
2387 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2388
2389 ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2390 ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
2391
2392 MsiCloseHandle(rec);
2393
2394 r = MsiViewFetch(view, &rec);
2395 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2396
2397 ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
2398 ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
2399
2400 MsiCloseHandle(rec);
2401
2402 r = MsiViewFetch(view, &rec);
2403 ok(r == ERROR_NO_MORE_ITEMS,
2404 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2405
2406 r = MsiViewClose(view);
2407 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2408
2409 MsiCloseHandle(view);
2410
2411 query = "SELECT * FROM `Table`";
2412 r = MsiDatabaseOpenViewA(hdb, query, &view);
2413 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2414
2415 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2416 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2417 count = MsiRecordGetFieldCount(rec);
2418 ok(count == 6, "Expected 6, got %d\n", count);
2419 ok(check_record(rec, 1, "A"), "Expected A\n");
2420 ok(check_record(rec, 2, "B"), "Expected B\n");
2421 ok(check_record(rec, 3, "C"), "Expected C\n");
2422 ok(check_record(rec, 4, "D"), "Expected D\n");
2423 ok(check_record(rec, 5, "E"), "Expected E\n");
2424 ok(check_record(rec, 6, "F"), "Expected F\n");
2425 MsiCloseHandle(rec);
2426
2427 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2428 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2429 count = MsiRecordGetFieldCount(rec);
2430 ok(count == 6, "Expected 6, got %d\n", count);
2431 ok(check_record(rec, 1, "s72"), "Expected s72\n");
2432 ok(check_record(rec, 2, "s72"), "Expected s72\n");
2433 ok(check_record(rec, 3, "s72"), "Expected s72\n");
2434 ok(check_record(rec, 4, "s72"), "Expected s72\n");
2435 ok(check_record(rec, 5, "s72"), "Expected s72\n");
2436 ok(check_record(rec, 6, "s72"), "Expected s72\n");
2437 MsiCloseHandle(rec);
2438
2439 MsiViewClose(view);
2440 MsiCloseHandle(view);
2441
2442 query = "SELECT * FROM `Table`";
2443 r = MsiDatabaseOpenViewA(hdb, query, &view);
2444 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2445
2446 r = MsiViewExecute(view, 0);
2447 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2448
2449 r = MsiViewFetch(view, &rec);
2450 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2451 ok(check_record(rec, 1, "a"), "Expected 'a'\n");
2452 ok(check_record(rec, 2, "b"), "Expected 'b'\n");
2453 ok(check_record(rec, 3, "c"), "Expected 'c'\n");
2454 ok(check_record(rec, 4, "d"), "Expected 'd'\n");
2455 ok(check_record(rec, 5, "e"), "Expected 'e'\n");
2456 ok(check_record(rec, 6, "f"), "Expected 'f'\n");
2457
2458 MsiCloseHandle(rec);
2459
2460 r = MsiViewFetch(view, &rec);
2461 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2462 ok(check_record(rec, 1, "g"), "Expected 'g'\n");
2463 ok(check_record(rec, 2, "h"), "Expected 'h'\n");
2464 ok(check_record(rec, 3, "i"), "Expected 'i'\n");
2465 ok(check_record(rec, 4, "j"), "Expected 'j'\n");
2466 ok(check_record(rec, 5, "k"), "Expected 'k'\n");
2467 ok(check_record(rec, 6, "l"), "Expected 'l'\n");
2468
2469 MsiCloseHandle(rec);
2470
2471 r = MsiViewFetch(view, &rec);
2472 ok(r == ERROR_NO_MORE_ITEMS,
2473 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2474
2475 MsiViewClose(view);
2476 MsiCloseHandle(view);
2477 MsiCloseHandle(hdb);
2478 DeleteFileA(msifile);
2479 }
2480
2481 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2482 "s72\tV0\r\n"
2483 "Binary\tName\r\n"
2484 "filename1\tfilename1.ibd\r\n";
2485
2486 static void test_binary_import(void)
2487 {
2488 MSIHANDLE hdb = 0, rec;
2489 char file[MAX_PATH];
2490 char buf[MAX_PATH];
2491 char path[MAX_PATH];
2492 DWORD size;
2493 LPCSTR query;
2494 UINT r;
2495
2496 /* create files to import */
2497 write_file("bin_import.idt", bin_import_dat,
2498 (sizeof(bin_import_dat) - 1) * sizeof(char));
2499 CreateDirectoryA("bin_import", NULL);
2500 create_file_data("bin_import/filename1.ibd", "just some words", 15);
2501
2502 /* import files into database */
2503 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2504 ok( r == ERROR_SUCCESS , "Failed to open database\n");
2505
2506 GetCurrentDirectoryA(MAX_PATH, path);
2507 r = MsiDatabaseImportA(hdb, path, "bin_import.idt");
2508 ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2509
2510 /* read file from the Binary table */
2511 query = "SELECT * FROM `Binary`";
2512 r = do_query(hdb, query, &rec);
2513 ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2514
2515 size = MAX_PATH;
2516 r = MsiRecordGetStringA(rec, 1, file, &size);
2517 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2518 ok(!lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file);
2519
2520 size = MAX_PATH;
2521 memset(buf, 0, MAX_PATH);
2522 r = MsiRecordReadStream(rec, 2, buf, &size);
2523 ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2524 ok(!lstrcmpA(buf, "just some words"), "Expected 'just some words', got %s\n", buf);
2525
2526 r = MsiCloseHandle(rec);
2527 ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2528
2529 r = MsiCloseHandle(hdb);
2530 ok(r == ERROR_SUCCESS , "Failed to close database\n");
2531
2532 DeleteFileA("bin_import/filename1.ibd");
2533 RemoveDirectoryA("bin_import");
2534 DeleteFileA("bin_import.idt");
2535 }
2536
2537 static void test_markers(void)
2538 {
2539 MSIHANDLE hdb, rec;
2540 LPCSTR query;
2541 UINT r;
2542
2543 hdb = create_db();
2544 ok( hdb, "failed to create db\n");
2545
2546 rec = MsiCreateRecord(3);
2547 MsiRecordSetStringA(rec, 1, "Table");
2548 MsiRecordSetStringA(rec, 2, "Apples");
2549 MsiRecordSetStringA(rec, 3, "Oranges");
2550
2551 /* try a legit create */
2552 query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2553 r = run_query(hdb, 0, query);
2554 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2555 MsiCloseHandle(rec);
2556
2557 /* try table name as marker */
2558 rec = MsiCreateRecord(1);
2559 MsiRecordSetStringA(rec, 1, "Fable");
2560 query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2561 r = run_query(hdb, rec, query);
2562 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2563
2564 /* verify that we just created a table called '?', not 'Fable' */
2565 r = try_query(hdb, "SELECT * from `Fable`");
2566 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2567
2568 r = try_query(hdb, "SELECT * from `?`");
2569 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2570
2571 /* try table name as marker without backticks */
2572 MsiRecordSetStringA(rec, 1, "Mable");
2573 query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2574 r = run_query(hdb, rec, query);
2575 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2576
2577 /* try one column name as marker */
2578 MsiRecordSetStringA(rec, 1, "One");
2579 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2580 r = run_query(hdb, rec, query);
2581 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2582 MsiCloseHandle(rec);
2583
2584 /* try column names as markers */
2585 rec = MsiCreateRecord(2);
2586 MsiRecordSetStringA(rec, 1, "One");
2587 MsiRecordSetStringA(rec, 2, "Two");
2588 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2589 r = run_query(hdb, rec, query);
2590 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2591 MsiCloseHandle(rec);
2592
2593 /* try names with backticks */
2594 rec = MsiCreateRecord(3);
2595 MsiRecordSetStringA(rec, 1, "One");
2596 MsiRecordSetStringA(rec, 2, "Two");
2597 MsiRecordSetStringA(rec, 3, "One");
2598 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2599 r = run_query(hdb, rec, query);
2600 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2601
2602 /* try names with backticks, minus definitions */
2603 query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2604 r = run_query(hdb, rec, query);
2605 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2606
2607 /* try names without backticks */
2608 query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2609 r = run_query(hdb, rec, query);
2610 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2611 MsiCloseHandle(rec);
2612
2613 /* try one long marker */
2614 rec = MsiCreateRecord(1);
2615 MsiRecordSetStringA(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2616 query = "CREATE TABLE `Mable` ( ? )";
2617 r = run_query(hdb, rec, query);
2618 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2619 MsiCloseHandle(rec);
2620
2621 /* try all names as markers */
2622 rec = MsiCreateRecord(4);
2623 MsiRecordSetStringA(rec, 1, "Mable");
2624 MsiRecordSetStringA(rec, 2, "One");
2625 MsiRecordSetStringA(rec, 3, "Two");
2626 MsiRecordSetStringA(rec, 4, "One");
2627 query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2628 r = run_query(hdb, rec, query);
2629 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2630 MsiCloseHandle(rec);
2631
2632 /* try a legit insert */
2633 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2634 r = run_query(hdb, 0, query);
2635 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2636
2637 r = try_query(hdb, "SELECT * from `Table`");
2638 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2639
2640 /* try values as markers */
2641 rec = MsiCreateRecord(2);
2642 MsiRecordSetInteger(rec, 1, 4);
2643 MsiRecordSetStringA(rec, 2, "hi");
2644 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2645 r = run_query(hdb, rec, query);
2646 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2647 MsiCloseHandle(rec);
2648
2649 /* try column names and values as markers */
2650 rec = MsiCreateRecord(4);
2651 MsiRecordSetStringA(rec, 1, "One");
2652 MsiRecordSetStringA(rec, 2, "Two");
2653 MsiRecordSetInteger(rec, 3, 5);
2654 MsiRecordSetStringA(rec, 4, "hi");
2655 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2656 r = run_query(hdb, rec, query);
2657 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2658 MsiCloseHandle(rec);
2659
2660 /* try column names as markers */
2661 rec = MsiCreateRecord(2);
2662 MsiRecordSetStringA(rec, 1, "One");
2663 MsiRecordSetStringA(rec, 2, "Two");
2664 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2665 r = run_query(hdb, rec, query);
2666 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2667 MsiCloseHandle(rec);
2668
2669 /* try table name as a marker */
2670 rec = MsiCreateRecord(1);
2671 MsiRecordSetStringA(rec, 1, "Table");
2672 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2673 r = run_query(hdb, rec, query);
2674 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2675 MsiCloseHandle(rec);
2676
2677 /* try table name and values as markers */
2678 rec = MsiCreateRecord(3);
2679 MsiRecordSetStringA(rec, 1, "Table");
2680 MsiRecordSetInteger(rec, 2, 10);
2681 MsiRecordSetStringA(rec, 3, "haha");
2682 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2683 r = run_query(hdb, rec, query);
2684 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2685 MsiCloseHandle(rec);
2686
2687 /* try all markers */
2688 rec = MsiCreateRecord(5);
2689 MsiRecordSetStringA(rec, 1, "Table");
2690 MsiRecordSetStringA(rec, 1, "One");
2691 MsiRecordSetStringA(rec, 1, "Two");
2692 MsiRecordSetInteger(rec, 2, 10);
2693 MsiRecordSetStringA(rec, 3, "haha");
2694 query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2695 r = run_query(hdb, rec, query);
2696 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2697 MsiCloseHandle(rec);
2698
2699 /* insert an integer as a string */
2700 rec = MsiCreateRecord(2);
2701 MsiRecordSetStringA(rec, 1, "11");
2702 MsiRecordSetStringA(rec, 2, "hi");
2703 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2704 r = run_query(hdb, rec, query);
2705 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2706 MsiCloseHandle(rec);
2707
2708 /* leave off the '' for the string */
2709 rec = MsiCreateRecord(2);
2710 MsiRecordSetInteger(rec, 1, 12);
2711 MsiRecordSetStringA(rec, 2, "hi");
2712 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2713 r = run_query(hdb, rec, query);
2714 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2715 MsiCloseHandle(rec);
2716
2717 MsiCloseHandle(hdb);
2718 DeleteFileA(msifile);
2719 }
2720
2721 #define MY_NVIEWS 4000 /* Largest installer I've seen uses < 2k */
2722 static void test_handle_limit(void)
2723 {
2724 int i;
2725 MSIHANDLE hdb;
2726 MSIHANDLE hviews[MY_NVIEWS];
2727 UINT r;
2728
2729 /* create an empty db */
2730 hdb = create_db();
2731 ok( hdb, "failed to create db\n");
2732
2733 memset(hviews, 0, sizeof(hviews));
2734
2735 for (i=0; i<MY_NVIEWS; i++) {
2736 static char szQueryBuf[256] = "SELECT * from `_Tables`";
2737 hviews[i] = 0xdeadbeeb;
2738 r = MsiDatabaseOpenViewA(hdb, szQueryBuf, &hviews[i]);
2739 if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb ||
2740 hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2741 break;
2742 }
2743
2744 ok( i == MY_NVIEWS, "problem opening views\n");
2745
2746 for (i=0; i<MY_NVIEWS; i++) {
2747 if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2748 MsiViewClose(hviews[i]);
2749 r = MsiCloseHandle(hviews[i]);
2750 if (r != ERROR_SUCCESS)
2751 break;
2752 }
2753 }
2754
2755 ok( i == MY_NVIEWS, "problem closing views\n");
2756
2757 r = MsiCloseHandle(hdb);
2758 ok( r == ERROR_SUCCESS, "failed to close database\n");
2759 }
2760
2761 static void generate_transform(void)
2762 {
2763 MSIHANDLE hdb1, hdb2, hrec;
2764 LPCSTR query;
2765 UINT r;
2766
2767 /* start with two identical databases */
2768 CopyFileA(msifile2, msifile, FALSE);
2769
2770 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb1 );
2771 ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2772
2773 r = MsiDatabaseCommit( hdb1 );
2774 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2775
2776 r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_READONLY, &hdb2 );
2777 ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2778
2779 /* the transform between two identical database should be empty */
2780 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, NULL, 0, 0);
2781 todo_wine {
2782 ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2783 }
2784
2785 query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2786 r = run_query(hdb1, 0, query);
2787 ok(r == ERROR_SUCCESS, "failed to add table\n");
2788
2789 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2790 r = run_query(hdb1, 0, query);
2791 ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2792
2793 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2794 r = run_query(hdb1, 0, query);
2795 ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2796
2797 query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2798 r = run_query(hdb1, 0, query);
2799 ok(r == ERROR_SUCCESS, "failed to modify row\n");
2800
2801 query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2802 r = run_query(hdb1, 0, query);
2803 ok(r == ERROR_SUCCESS, "failed to delete row\n");
2804
2805 hrec = MsiCreateRecord(2);
2806 r = MsiRecordSetInteger(hrec, 1, 1);
2807 ok(r == ERROR_SUCCESS, "failed to set integer\n");
2808
2809 write_file("testdata.bin", "naengmyon", 9);
2810 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin");
2811 ok(r == ERROR_SUCCESS, "failed to set stream\n");
2812
2813 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2814 r = run_query(hdb1, hrec, query);
2815 ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2816
2817 MsiCloseHandle(hrec);
2818
2819 query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2820 r = run_query(hdb1, 0, query);
2821 ok(r == ERROR_SUCCESS, "failed to add column\n");
2822
2823 query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2824 r = run_query(hdb1, 0, query);
2825 ok(r == ERROR_SUCCESS, "failed to add column\n");
2826
2827 query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2828 r = run_query(hdb1, 0, query);
2829 ok(r == ERROR_SUCCESS, "failed to modify row\n");
2830
2831 query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2832 "`Value` CHAR(0) PRIMARY KEY `Property`)";
2833 r = run_query(hdb1, 0, query);
2834 ok(r == ERROR_SUCCESS, "failed to add property table\n");
2835
2836 query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2837 r = run_query(hdb1, 0, query);
2838 ok(r == ERROR_SUCCESS, "failed to add property\n");
2839
2840 /* database needs to be committed */
2841 MsiDatabaseCommit(hdb1);
2842
2843 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, mstfile, 0, 0);
2844 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2845
2846 MsiCloseHandle( hdb1 );
2847 MsiCloseHandle( hdb2 );
2848
2849 DeleteFileA("testdata.bin");
2850 }
2851
2852 /* data for generating a transform */
2853
2854 /* tables transform names - encoded as they would be in an msi database file */
2855 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2856 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2857 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2858 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2859 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2860 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2861 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2862 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2863 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2864
2865 /* data in each table */
2866 static const WCHAR data1[] = { /* AAR */
2867 0x0201, 0x0008, 0x8001, /* 0x0201 = add row (1), two shorts */
2868 0x0201, 0x0009, 0x8002,
2869 };
2870 static const WCHAR data2[] = { /* _Columns */
2871 0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2872 0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2873 0x0401, 0x0005, 0x0000, 0x0006, 0xbdff, /* 0x0401 = add row (1), 4 shorts */
2874 0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2875 0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2876 0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2877 };
2878 static const WCHAR data3[] = { /* _Tables */
2879 0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2880 0x0101, 0x000a,
2881 };
2882 static const char data4[] = /* _StringData */
2883 "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval"; /* all the strings squashed together */
2884 static const WCHAR data5[] = { /* _StringPool */
2885 /* len, refs */
2886 0, 0, /* string 0 '' */
2887 3, 2, /* string 1 'MOO' */
2888 3, 1, /* string 2 'COW' */
2889 3, 1, /* string 3 'PIG' */
2890 1, 1, /* string 4 'c' */
2891 3, 3, /* string 5 'AAR' */
2892 3, 1, /* string 6 'CAR' */
2893 3, 1, /* string 7 'BAR' */
2894 2, 1, /* string 8 'vw' */
2895 3, 1, /* string 9 'bmw' */
2896 8, 4, /* string 10 'Property' */
2897 5, 1, /* string 11 'Value' */
2898 4, 1, /* string 12 'prop' */
2899 3, 1, /* string 13 'val' */
2900 };
2901 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2902 static const WCHAR data6[] = { /* MOO */
2903 0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2904 0x0000, 0x8003, /* delete row */
2905 };
2906
2907 static const WCHAR data7[] = { /* BINARY */
2908 0x0201, 0x8001, 0x0001,
2909 };
2910
2911 static const char data8[] = /* stream data for the BINARY table */
2912 "naengmyon";
2913
2914 static const WCHAR data9[] = { /* Property */
2915 0x0201, 0x000c, 0x000d,
2916 };
2917
2918 static const struct {
2919 LPCWSTR name;
2920 const void *data;
2921 DWORD size;
2922 } table_transform_data[] =
2923 {
2924 { name1, data1, sizeof data1 },
2925 { name2, data2, sizeof data2 },
2926 { name3, data3, sizeof data3 },
2927 { name4, data4, sizeof data4 - 1 },
2928 { name5, data5, sizeof data5 },
2929 { name6, data6, sizeof data6 },
2930 { name7, data7, sizeof data7 },
2931 { name8, data8, sizeof data8 - 1 },
2932 { name9, data9, sizeof data9 },
2933 };
2934
2935 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2936
2937 static void generate_transform_manual(void)
2938 {
2939 IStorage *stg = NULL;
2940 IStream *stm;
2941 WCHAR name[0x20];
2942 HRESULT r;
2943 DWORD i, count;
2944 const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2945
2946 const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2947
2948 MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2949
2950 r = StgCreateDocfile(name, mode, 0, &stg);
2951 ok(r == S_OK, "failed to create storage\n");
2952 if (!stg)
2953 return;
2954
2955 r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2956 ok(r == S_OK, "failed to set storage type\n");
2957
2958 for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2959 {
2960 r = IStorage_CreateStream( stg, table_transform_data[i].name,
2961 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2962 if (FAILED(r))
2963 {
2964 ok(0, "failed to create stream %08x\n", r);
2965 continue;
2966 }
2967
2968 r = IStream_Write( stm, table_transform_data[i].data,
2969 table_transform_data[i].size, &count );
2970 if (FAILED(r) || count != table_transform_data[i].size)
2971 ok(0, "failed to write stream\n");
2972 IStream_Release(stm);
2973 }
2974
2975 IStorage_Release(stg);
2976 }
2977
2978 static UINT set_summary_info(MSIHANDLE hdb)
2979 {
2980 UINT res;
2981 MSIHANDLE suminfo;
2982
2983 /* build summary info */
2984 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
2985 ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2986
2987 res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
2988 "Installation Database");
2989 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2990
2991 res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
2992 "Installation Database");
2993 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2994
2995 res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
2996 "Wine Hackers");
2997 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2998
2999 res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
3000 ";1033,2057");
3001 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3002
3003 res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
3004 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
3005 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3006
3007 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
3008 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3009
3010 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
3011 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3012
3013 res = MsiSummaryInfoPersist(suminfo);
3014 ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
3015
3016 res = MsiCloseHandle( suminfo);
3017 ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
3018
3019 return res;
3020 }
3021
3022 static MSIHANDLE create_package_db(const WCHAR *filename)
3023 {
3024 MSIHANDLE hdb = 0;
3025 UINT res;
3026
3027 DeleteFileW(msifileW);
3028
3029 /* create an empty database */
3030 res = MsiOpenDatabaseW(filename, MSIDBOPEN_CREATE, &hdb );
3031 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
3032 if( res != ERROR_SUCCESS )
3033 return hdb;
3034
3035 res = MsiDatabaseCommit( hdb );
3036 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
3037
3038 res = set_summary_info(hdb);
3039 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3040
3041 res = create_directory_table(hdb);
3042 ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
3043
3044 return hdb;
3045 }
3046
3047 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
3048 {
3049 UINT res;
3050 CHAR szPackage[12];
3051 MSIHANDLE hPackage;
3052
3053 sprintf(szPackage, "#%u", hdb);
3054 res = MsiOpenPackageA(szPackage, &hPackage);
3055 if (res != ERROR_SUCCESS)
3056 return res;
3057
3058 res = MsiCloseHandle(hdb);
3059 if (res != ERROR_SUCCESS)
3060 {
3061 MsiCloseHandle(hPackage);
3062 return res;
3063 }
3064
3065 *handle = hPackage;
3066 return ERROR_SUCCESS;
3067 }
3068
3069 static void test_try_transform(void)
3070 {
3071 MSIHANDLE hdb, hview, hrec, hpkg = 0;
3072 LPCSTR query;
3073 UINT r;
3074 DWORD sz;
3075 char buffer[MAX_PATH];
3076
3077 DeleteFileA(msifile);
3078 DeleteFileA(mstfile);
3079
3080 /* create the database */
3081 hdb = create_package_db(msifileW);
3082 ok(hdb, "Failed to create package db\n");
3083
3084 query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
3085 r = run_query(hdb, 0, query);
3086 ok(r == ERROR_SUCCESS, "failed to add table\n");
3087
3088 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
3089 r = run_query(hdb, 0, query);
3090 ok(r == ERROR_SUCCESS, "failed to add row\n");
3091
3092 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
3093 r = run_query(hdb, 0, query);
3094 ok(r == ERROR_SUCCESS, "failed to add row\n");
3095
3096 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
3097 r = run_query(hdb, 0, query);
3098 ok(r == ERROR_SUCCESS, "failed to add row\n");
3099
3100 query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
3101 r = run_query(hdb, 0, query);
3102 ok(r == ERROR_SUCCESS, "failed to add table\n");
3103
3104 hrec = MsiCreateRecord(2);
3105 r = MsiRecordSetInteger(hrec, 1, 2);
3106 ok(r == ERROR_SUCCESS, "failed to set integer\n");
3107
3108 write_file("testdata.bin", "lamyon", 6);
3109 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin");
3110 ok(r == ERROR_SUCCESS, "failed to set stream\n");
3111
3112 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3113 r = run_query(hdb, hrec, query);
3114 ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3115
3116 MsiCloseHandle(hrec);
3117
3118 r = MsiDatabaseCommit( hdb );
3119 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3120
3121 MsiCloseHandle( hdb );
3122 DeleteFileA("testdata.bin");
3123
3124 /*
3125 * Both these generate an equivalent transform,
3126 * but the first doesn't work in Wine yet
3127 * because MsiDatabaseGenerateTransform is unimplemented.
3128 */
3129 if (0)
3130 generate_transform();
3131 else
3132 generate_transform_manual();
3133
3134 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb );
3135 ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3136
3137 r = MsiDatabaseApplyTransformA( hdb, mstfile, 0 );
3138 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3139
3140 MsiDatabaseCommit( hdb );
3141
3142 /* check new values */
3143 hrec = 0;
3144 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3145 r = do_query(hdb, query, &hrec);
3146 ok(r == ERROR_SUCCESS, "select query failed\n");
3147 MsiCloseHandle(hrec);
3148
3149 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3150 hrec = 0;
3151 r = do_query(hdb, query, &hrec);
3152 ok(r == ERROR_SUCCESS, "select query failed\n");
3153 MsiCloseHandle(hrec);
3154
3155 /* check updated values */
3156 hrec = 0;
3157 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3158 r = do_query(hdb, query, &hrec);
3159 ok(r == ERROR_SUCCESS, "select query failed\n");
3160 MsiCloseHandle(hrec);
3161
3162 /* check unchanged value */
3163 hrec = 0;
3164 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3165 r = do_query(hdb, query, &hrec);
3166 ok(r == ERROR_SUCCESS, "select query failed\n");
3167 MsiCloseHandle(hrec);
3168
3169 /* check deleted value */
3170 hrec = 0;
3171 query = "select * from `MOO` where `NOO` = 3";
3172 r = do_query(hdb, query, &hrec);
3173 ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3174 if (hrec) MsiCloseHandle(hrec);
3175
3176 /* check added stream */
3177 hrec = 0;
3178 query = "select `BLOB` from `BINARY` where `ID` = 1";
3179 r = do_query(hdb, query, &hrec);
3180 ok(r == ERROR_SUCCESS, "select query failed\n");
3181
3182 /* check the contents of the stream */
3183 sz = sizeof buffer;
3184 r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3185 ok(r == ERROR_SUCCESS, "read stream failed\n");
3186 ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3187 ok(sz == 9, "stream data was wrong size\n");
3188 if (hrec) MsiCloseHandle(hrec);
3189
3190 /* check the validity of the table with a deleted row */
3191 hrec = 0;
3192 query = "select * from `MOO`";
3193 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3194 ok(r == ERROR_SUCCESS, "open view failed\n");
3195
3196 r = MsiViewExecute(hview, 0);
3197 ok(r == ERROR_SUCCESS, "view execute failed\n");
3198
3199 r = MsiViewFetch(hview, &hrec);
3200 ok(r == ERROR_SUCCESS, "view fetch failed\n");
3201
3202 r = MsiRecordGetInteger(hrec, 1);
3203 ok(r == 1, "Expected 1, got %d\n", r);
3204
3205 sz = sizeof buffer;
3206 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
3207 ok(r == ERROR_SUCCESS, "record get string failed\n");
3208 ok(!lstrcmpA(buffer, "c"), "Expected c, got %s\n", buffer);
3209
3210 r = MsiRecordGetInteger(hrec, 3);
3211 ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3212
3213 r = MsiRecordGetInteger(hrec, 4);
3214 ok(r == 5, "Expected 5, got %d\n", r);
3215
3216 MsiCloseHandle(hrec);
3217
3218 r = MsiViewFetch(hview, &hrec);
3219 ok(r == ERROR_SUCCESS, "view fetch failed\n");
3220
3221 r = MsiRecordGetInteger(hrec, 1);
3222 ok(r == 2, "Expected 2, got %d\n", r);
3223
3224 sz = sizeof buffer;
3225 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
3226 ok(r == ERROR_SUCCESS, "record get string failed\n");
3227 ok(!lstrcmpA(buffer, "b"), "Expected b, got %s\n", buffer);
3228
3229 r = MsiRecordGetInteger(hrec, 3);
3230 ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3231
3232 r = MsiRecordGetInteger(hrec, 4);
3233 ok(r == 0x80000000, "Expected 0x80000000, got %d\n", r);
3234
3235 MsiCloseHandle(hrec);
3236
3237 r = MsiViewFetch(hview, &hrec);
3238 ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3239
3240 MsiCloseHandle(hrec);
3241 MsiViewClose(hview);
3242 MsiCloseHandle(hview);
3243
3244 /* check that the property was added */
3245 r = package_from_db(hdb, &hpkg);
3246 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3247 {
3248 skip("Not enough rights to perform tests\n");
3249 goto error;
3250 }
3251 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3252
3253 sz = MAX_PATH;
3254 r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
3255 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3256 ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
3257
3258 MsiCloseHandle(hpkg);
3259
3260 error:
3261 MsiCloseHandle(hdb);
3262 DeleteFileA(msifile);
3263 DeleteFileA(mstfile);
3264 }
3265
3266 struct join_res
3267 {
3268 const CHAR one[MAX_PATH];
3269 const CHAR two[MAX_PATH];
3270 };
3271
3272 struct join_res_4col
3273 {
3274 const CHAR one[MAX_PATH];
3275 const CHAR two[MAX_PATH];
3276 const CHAR three[MAX_PATH];
3277 const CHAR four[MAX_PATH];
3278 };
3279
3280 struct join_res_uint
3281 {
3282 UINT one;
3283 UINT two;
3284 UINT three;
3285 UINT four;
3286 UINT five;
3287 UINT six;
3288 };
3289
3290 static const struct join_res join_res_first[] =
3291 {
3292 { "alveolar", "procerus" },
3293 { "septum", "procerus" },
3294 { "septum", "nasalis" },
3295 { "ramus", "nasalis" },
3296 { "malar", "mentalis" },
3297 };
3298
3299 static const struct join_res join_res_second[] =
3300 {
3301 { "nasal", "septum" },
3302 { "mandible", "ramus" },
3303 };
3304
3305 static const struct join_res join_res_third[] =
3306 {
3307 { "msvcp.dll", "abcdefgh" },
3308 { "msvcr.dll", "ijklmnop" },
3309 };
3310
3311 static const struct join_res join_res_fourth[] =
3312 {
3313 { "msvcp.dll.01234", "single.dll.31415" },
3314 };
3315
3316 static const struct join_res join_res_fifth[] =
3317 {
3318 { "malar", "procerus" },
3319 };
3320
3321 static const struct join_res join_res_sixth[] =
3322 {
3323 { "malar", "procerus" },
3324 { "malar", "procerus" },
3325 { "malar", "nasalis" },
3326 { "malar", "nasalis" },
3327 { "malar", "nasalis" },
3328 { "malar", "mentalis" },
3329 };
3330
3331 static const struct join_res join_res_seventh[] =
3332 {
3333 { "malar", "nasalis" },
3334 { "malar", "nasalis" },
3335 { "malar", "nasalis" },
3336 };
3337
3338 static const struct join_res_4col join_res_eighth[] =
3339 {
3340 { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3341 { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3342 { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3343 { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3344 { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3345 { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3346 };
3347
3348 static const struct join_res_uint join_res_ninth[] =
3349 {
3350 { 1, 2, 3, 4, 7, 8 },
3351 { 1, 2, 5, 6, 7, 8 },
3352 { 1, 2, 3, 4, 9, 10 },
3353 { 1, 2, 5, 6, 9, 10 },
3354 { 1, 2, 3, 4, 11, 12 },
3355 { 1, 2, 5, 6, 11, 12 },
3356 };
3357
3358 static void test_join(void)
3359 {
3360 MSIHANDLE hdb, hview, hrec;
3361 LPCSTR query;
3362 CHAR buf[MAX_PATH];
3363 UINT r, count;
3364 DWORD size, i;
3365 BOOL data_correct;
3366
3367 hdb = create_db();
3368 ok( hdb, "failed to create db\n");
3369
3370 r = create_component_table( hdb );
3371 ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3372
3373 r = add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3374 ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3375
3376 r = add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3377 ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3378
3379 r = add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3380 ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3381
3382 r = add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3383 ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3384
3385 r = create_feature_components_table( hdb );
3386 ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3387
3388 r = add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3389 ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3390
3391 r = add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3392 ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3393
3394 r = add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3395 ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3396
3397 r = add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3398 ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3399
3400 r = add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3401 ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3402
3403 r = add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3404 ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3405
3406 r = create_std_dlls_table( hdb );
3407 ok( r == ERROR_SUCCESS, "cannot create StdDlls table: %d\n", r );
3408
3409 r = add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3410 ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3411
3412 r = add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3413 ok( r == ERROR_SUCCESS, "cannot add std dlls: %d\n", r );
3414
3415 r = create_binary_table( hdb );
3416 ok( r == ERROR_SUCCESS, "cannot create Binary table: %d\n", r );
3417
3418 r = add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3419 ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3420
3421 r = add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3422 ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3423
3424 r = add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3425 ok( r == ERROR_SUCCESS, "cannot add binary: %d\n", r );
3426
3427 query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3428 r = run_query( hdb, 0, query);
3429 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3430
3431 query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3432 r = run_query( hdb, 0, query);
3433 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3434
3435 query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3436 r = run_query( hdb, 0, query);
3437 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3438
3439 query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3440 r = run_query( hdb, 0, query);
3441 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3442
3443 query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3444 r = run_query( hdb, 0, query);
3445 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3446
3447 query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3448 r = run_query( hdb, 0, query);
3449 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3450
3451 query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3452 r = run_query( hdb, 0, query);
3453 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3454
3455 query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3456 r = run_query( hdb, 0, query);
3457 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3458
3459 query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3460 r = run_query( hdb, 0, query);
3461 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3462
3463 query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3464 r = run_query( hdb, 0, query);
3465 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3466
3467 query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3468 r = run_query( hdb, 0, query);
3469 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3470
3471 query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3472 r = run_query( hdb, 0, query);
3473 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3474
3475 query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3476 r = run_query( hdb, 0, query);
3477 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3478
3479 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3480 "FROM `Component`, `FeatureComponents` "
3481 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3482 "ORDER BY `Feature_`";
3483 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3484 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3485
3486 r = MsiViewExecute(hview, 0);
3487 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3488
3489 i = 0;
3490 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3491 {
3492 count = MsiRecordGetFieldCount( hrec );
3493 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3494
3495 size = MAX_PATH;
3496 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3497 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3498 ok( !lstrcmpA( buf, join_res_first[i].one ),
3499 "For (row %d, column 1) expected '%s', got %s\n", i, join_res_first[i].one, buf );
3500
3501 size = MAX_PATH;
3502 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3503 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3504 ok( !lstrcmpA( buf, join_res_first[i].two ),
3505 "For (row %d, column 2) expected '%s', got %s\n", i, join_res_first[i].two, buf );
3506
3507 i++;
3508 MsiCloseHandle(hrec);
3509 }
3510
3511 ok( i == 5, "Expected 5 rows, got %d\n", i );
3512 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3513
3514 MsiViewClose(hview);
3515 MsiCloseHandle(hview);
3516
3517 /* try a join without a WHERE condition */
3518 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3519 "FROM `Component`, `FeatureComponents` ";
3520 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3521 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3522
3523 r = MsiViewExecute(hview, 0);
3524 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3525
3526 i = 0;
3527 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3528 {
3529 i++;
3530 MsiCloseHandle(hrec);
3531 }
3532 ok( i == 24, "Expected 24 rows, got %d\n", i );
3533
3534 MsiViewClose(hview);
3535 MsiCloseHandle(hview);
3536
3537 query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3538 "WHERE FeatureComponents.Component_=Component.Component "
3539 "AND (Feature_='nasalis') ORDER BY Feature_";
3540 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3541 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3542
3543 r = MsiViewExecute(hview, 0);
3544 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3545
3546 i = 0;
3547 data_correct = TRUE;
3548 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3549 {
3550 count = MsiRecordGetFieldCount( hrec );
3551 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3552
3553 size = MAX_PATH;
3554 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3555 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3556 if( lstrcmpA( buf, join_res_second[i].one ))
3557 data_correct = FALSE;
3558
3559 size = MAX_PATH;
3560 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3561 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3562 if( lstrcmpA( buf, join_res_second[i].two ))
3563 data_correct = FALSE;
3564
3565 i++;
3566 MsiCloseHandle(hrec);
3567 }
3568
3569 ok( data_correct, "data returned in the wrong order\n");
3570
3571 ok( i == 2, "Expected 2 rows, got %d\n", i );
3572 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3573
3574 MsiViewClose(hview);
3575 MsiCloseHandle(hview);
3576
3577 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3578 "FROM `StdDlls`, `Binary` "
3579 "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3580 "ORDER BY `File`";
3581 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3582 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3583
3584 r = MsiViewExecute(hview, 0);
3585 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3586
3587 i = 0;
3588 data_correct = TRUE;
3589 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3590 {
3591 count = MsiRecordGetFieldCount( hrec );
3592 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3593
3594 size = MAX_PATH;
3595 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3596 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3597 if( lstrcmpA( buf, join_res_third[i].one ) )
3598 data_correct = FALSE;
3599
3600 size = MAX_PATH;
3601 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3602 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3603 if( lstrcmpA( buf, join_res_third[i].two ) )
3604 data_correct = FALSE;
3605
3606 i++;
3607 MsiCloseHandle(hrec);
3608 }
3609 ok( data_correct, "data returned in the wrong order\n");
3610
3611 ok( i == 2, "Expected 2 rows, got %d\n", i );
3612
3613 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3614
3615 MsiViewClose(hview);
3616 MsiCloseHandle(hview);
3617
3618 query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3619 "FROM `StdDlls`, `Binary` "
3620 "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3621 "ORDER BY `Name`";
3622 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3623 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3624
3625 r = MsiViewExecute(hview, 0);
3626 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3627
3628 i = 0;
3629 data_correct = TRUE;
3630 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3631 {
3632 count = MsiRecordGetFieldCount( hrec );
3633 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3634
3635 size = MAX_PATH;
3636 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3637 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3638 if( lstrcmpA( buf, join_res_fourth[i].one ))
3639 data_correct = FALSE;
3640
3641 size = MAX_PATH;
3642 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3643 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3644 if( lstrcmpA( buf, join_res_fourth[i].two ))
3645 data_correct = FALSE;
3646
3647 i++;
3648 MsiCloseHandle(hrec);
3649 }
3650 ok( data_correct, "data returned in the wrong order\n");
3651
3652 ok( i == 1, "Expected 1 rows, got %d\n", i );
3653 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3654
3655 MsiViewClose(hview);
3656 MsiCloseHandle(hview);
3657
3658 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3659 "FROM `Component`, `FeatureComponents` "
3660 "WHERE `Component`.`Component` = 'zygomatic' "
3661 "AND `FeatureComponents`.`Component_` = 'maxilla' "
3662 "ORDER BY `Feature_`";
3663 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3664 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3665
3666 r = MsiViewExecute(hview, 0);
3667 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3668
3669 i = 0;
3670 data_correct = TRUE;
3671 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3672 {
3673 count = MsiRecordGetFieldCount( hrec );
3674 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3675
3676 size = MAX_PATH;
3677 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3678 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3679 if( lstrcmpA( buf, join_res_fifth[i].one ))
3680 data_correct = FALSE;
3681
3682 size = MAX_PATH;
3683 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3684 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3685 if( lstrcmpA( buf, join_res_fifth[i].two ))
3686 data_correct = FALSE;
3687
3688 i++;
3689 MsiCloseHandle(hrec);
3690 }
3691 ok( data_correct, "data returned in the wrong order\n");
3692
3693 ok( i == 1, "Expected 1 rows, got %d\n", i );
3694 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3695
3696 MsiViewClose(hview);
3697 MsiCloseHandle(hview);
3698
3699 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3700 "FROM `Component`, `FeatureComponents` "
3701 "WHERE `Component` = 'zygomatic' "
3702 "ORDER BY `Feature_`";
3703 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3704 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3705
3706 r = MsiViewExecute(hview, 0);
3707 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3708
3709 i = 0;
3710 data_correct = TRUE;
3711 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3712 {
3713 count = MsiRecordGetFieldCount( hrec );
3714 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3715
3716 size = MAX_PATH;
3717 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3718 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3719 if( lstrcmpA( buf, join_res_sixth[i].one ))
3720 data_correct = FALSE;
3721
3722 size = MAX_PATH;
3723 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3724 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3725 if( lstrcmpA( buf, join_res_sixth[i].two ))
3726 data_correct = FALSE;
3727
3728 i++;
3729 MsiCloseHandle(hrec);
3730 }
3731 ok( data_correct, "data returned in the wrong order\n");
3732
3733 ok( i == 6, "Expected 6 rows, got %d\n", i );
3734 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3735
3736 MsiViewClose(hview);
3737 MsiCloseHandle(hview);
3738
3739 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3740 "FROM `Component`, `FeatureComponents` "
3741 "WHERE `Component` = 'zygomatic' "
3742 "AND `Feature_` = 'nasalis' "
3743 "ORDER BY `Feature_`";
3744 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3745 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3746
3747 r = MsiViewExecute(hview, 0);
3748 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3749
3750 i = 0;
3751 data_correct = TRUE;
3752 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3753 {
3754 count = MsiRecordGetFieldCount( hrec );
3755 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3756
3757 size = MAX_PATH;
3758 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3759 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3760 if( lstrcmpA( buf, join_res_seventh[i].one ))
3761 data_correct = FALSE;
3762
3763 size = MAX_PATH;
3764 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3765 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3766 if( lstrcmpA( buf, join_res_seventh[i].two ))
3767 data_correct = FALSE;
3768
3769 i++;
3770 MsiCloseHandle(hrec);
3771 }
3772
3773 ok( data_correct, "data returned in the wrong order\n");
3774 ok( i == 3, "Expected 3 rows, got %d\n", i );
3775 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3776
3777 MsiViewClose(hview);
3778 MsiCloseHandle(hview);
3779
3780 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3781 "FROM `StdDlls`, `Binary` ";
3782 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3783 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3784
3785 r = MsiViewExecute(hview, 0);
3786 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3787
3788 i = 0;
3789 data_correct = TRUE;
3790 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3791 {
3792 count = MsiRecordGetFieldCount( hrec );
3793 ok( count == 2, "Expected 2 record fields, got %d\n", count );
3794
3795 size = MAX_PATH;
3796 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3797 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3798 if( lstrcmpA( buf, join_res_eighth[i].one ))
3799 data_correct = FALSE;
3800
3801 size = MAX_PATH;
3802 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3803 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3804 if( lstrcmpA( buf, join_res_eighth[i].four ))
3805 data_correct = FALSE;
3806
3807 i++;
3808 MsiCloseHandle(hrec);
3809 }
3810
3811 ok( data_correct, "data returned in the wrong order\n");
3812 ok( i == 6, "Expected 6 rows, got %d\n", i );
3813 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3814
3815 MsiViewClose(hview);
3816 MsiCloseHandle(hview);
3817
3818 query = "SELECT * FROM `StdDlls`, `Binary` ";
3819 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3820 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3821
3822 r = MsiViewExecute(hview, 0);
3823 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3824
3825 i = 0;
3826 data_correct = TRUE;
3827 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3828 {
3829 count = MsiRecordGetFieldCount( hrec );
3830 ok( count == 4, "Expected 4 record fields, got %d\n", count );
3831
3832 size = MAX_PATH;
3833 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3834 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3835 if( lstrcmpA( buf, join_res_eighth[i].one ))
3836 data_correct = FALSE;
3837
3838 size = MAX_PATH;
3839 r = MsiRecordGetStringA( hrec, 2, buf, &size );
3840 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3841 if( lstrcmpA( buf, join_res_eighth[i].two ))
3842 data_correct = FALSE;
3843
3844 size = MAX_PATH;
3845 r = MsiRecordGetStringA( hrec, 3, buf, &size );
3846 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3847 if( lstrcmpA( buf, join_res_eighth[i].three ))
3848 data_correct = FALSE;
3849
3850 size = MAX_PATH;
3851 r = MsiRecordGetStringA( hrec, 4, buf, &size );
3852 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3853 if( lstrcmpA( buf, join_res_eighth[i].four ))
3854 data_correct = FALSE;
3855
3856 i++;
3857 MsiCloseHandle(hrec);
3858 }
3859 ok( data_correct, "data returned in the wrong order\n");
3860
3861 ok( i == 6, "Expected 6 rows, got %d\n", i );
3862 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3863
3864 MsiViewClose(hview);
3865 MsiCloseHandle(hview);
3866
3867 query = "SELECT * FROM `One`, `Two`, `Three` ";
3868 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3869 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3870
3871 r = MsiViewExecute(hview, 0);
3872 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3873
3874 i = 0;
3875 data_correct = TRUE;
3876 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3877 {
3878 count = MsiRecordGetFieldCount( hrec );
3879 ok( count == 6, "Expected 6 record fields, got %d\n", count );
3880
3881 r = MsiRecordGetInteger( hrec, 1 );
3882 if( r != join_res_ninth[i].one )
3883 data_correct = FALSE;
3884
3885 r = MsiRecordGetInteger( hrec, 2 );
3886 if( r != join_res_ninth[i].two )
3887 data_correct = FALSE;
3888
3889 r = MsiRecordGetInteger( hrec, 3 );
3890 if( r != join_res_ninth[i].three )
3891 data_correct = FALSE;
3892
3893 r = MsiRecordGetInteger( hrec, 4 );
3894 if( r != join_res_ninth[i].four )
3895 data_correct = FALSE;
3896
3897 r = MsiRecordGetInteger( hrec, 5 );
3898 if( r != join_res_ninth[i].five )
3899 data_correct = FALSE;
3900
3901 r = MsiRecordGetInteger( hrec, 6);
3902 if( r != join_res_ninth[i].six )
3903 data_correct = FALSE;
3904
3905 i++;
3906 MsiCloseHandle(hrec);
3907 }
3908 ok( data_correct, "data returned in the wrong order\n");
3909
3910 ok( i == 6, "Expected 6 rows, got %d\n", i );
3911 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3912
3913 MsiViewClose(hview);
3914 MsiCloseHandle(hview);
3915
3916 query = "SELECT * FROM `Four`, `Five`";
3917 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3918 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3919
3920 r = MsiViewExecute(hview, 0);
3921 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3922
3923 r = MsiViewFetch(hview, &hrec);
3924 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3925
3926 MsiViewClose(hview);
3927 MsiCloseHandle(hview);
3928
3929 query = "SELECT * FROM `Nonexistent`, `One`";
3930 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3931 ok( r == ERROR_BAD_QUERY_SYNTAX,
3932 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3933
3934 /* try updating a row in a join table */
3935 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3936 "FROM `Component`, `FeatureComponents` "
3937 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3938 "ORDER BY `Feature_`";
3939 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3940 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3941
3942 r = MsiViewExecute(hview, 0);
3943 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3944
3945 r = MsiViewFetch(hview, &hrec);
3946 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3947
3948 r = MsiRecordSetStringA( hrec, 1, "epicranius" );
3949 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3950
3951 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3952 ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3953
3954 /* try another valid operation for joins */
3955 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3956 todo_wine ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3957
3958 /* try an invalid operation for joins */
3959 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3960 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3961
3962 r = MsiRecordSetStringA( hrec, 2, "epicranius" );
3963 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3964
3965 /* primary key cannot be updated */
3966 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3967 ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3968
3969 MsiCloseHandle(hrec);
3970 MsiViewClose(hview);
3971 MsiCloseHandle(hview);
3972
3973 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3974 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3975
3976 r = MsiViewExecute(hview, 0);
3977 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3978
3979 r = MsiViewFetch(hview, &hrec);
3980 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3981
3982 size = MAX_PATH;
3983 r = MsiRecordGetStringA( hrec, 1, buf, &size );
3984 ok( r == ERROR_SUCCESS, "failed to get record string: %d\n", r );
3985 ok( !lstrcmpA( buf, "epicranius" ), "expected 'epicranius', got %s\n", buf );
3986
3987 MsiCloseHandle(hrec);
3988 MsiViewClose(hview);
3989 MsiCloseHandle(hview);
3990
3991 MsiCloseHandle(hdb);
3992 DeleteFileA(msifile);
3993 }
3994
3995 static void test_temporary_table(void)
3996 {
3997 MSICONDITION cond;
3998 MSIHANDLE hdb = 0, view = 0, rec;
3999 const char *query;
4000 UINT r;
4001 char buf[0x10];
4002 DWORD sz;
4003
4004 cond = MsiDatabaseIsTablePersistentA(0, NULL);
4005 ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
4006
4007 hdb = create_db();
4008 ok( hdb, "failed to create db\n");
4009
4010 cond = MsiDatabaseIsTablePersistentA(hdb, NULL);
4011 ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
4012
4013 cond = MsiDatabaseIsTablePersistentA(hdb, "_Tables");
4014 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4015
4016 cond = MsiDatabaseIsTablePersistentA(hdb, "_Columns");
4017 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4018
4019 cond = MsiDatabaseIsTablePersistentA(hdb, "_Storages");
4020 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4021
4022 cond = MsiDatabaseIsTablePersistentA(hdb, "_Streams");
4023 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4024
4025 query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
4026 r = run_query(hdb, 0, query);
4027 ok(r == ERROR_SUCCESS, "failed to add table\n");
4028
4029 cond = MsiDatabaseIsTablePersistentA(hdb, "P");
4030 ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4031
4032 query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
4033 r = run_query(hdb, 0, query);
4034 ok(r == ERROR_SUCCESS, "failed to add table\n");
4035
4036 cond = MsiDatabaseIsTablePersistentA(hdb, "P2");
4037 ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4038
4039 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4040 r = run_query(hdb, 0, query);
4041 ok(r == ERROR_SUCCESS, "failed to add table\n");
4042
4043 cond = MsiDatabaseIsTablePersistentA(hdb, "T");
4044 ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4045
4046 query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4047 r = run_query(hdb, 0, query);
4048 ok(r == ERROR_SUCCESS, "failed to add table\n");
4049
4050 query = "SELECT * FROM `T2`";
4051 r = MsiDatabaseOpenViewA(hdb, query, &view);
4052 ok(r == ERROR_BAD_QUERY_SYNTAX,
4053 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4054
4055 cond = MsiDatabaseIsTablePersistentA(hdb, "T2");
4056 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4057
4058 query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
4059 r = run_query(hdb, 0, query);
4060 ok(r == ERROR_SUCCESS, "failed to add table\n");
4061
4062 cond = MsiDatabaseIsTablePersistentA(hdb, "T3");
4063 ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
4064
4065 query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
4066 r = run_query(hdb, 0, query);
4067 ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
4068
4069 cond = MsiDatabaseIsTablePersistentA(hdb, "T4");
4070 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
4071
4072 query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
4073 r = run_query(hdb, 0, query);
4074 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
4075
4076 query = "select * from `T`";
4077 r = MsiDatabaseOpenViewA(hdb, query, &view);
4078 ok(r == ERROR_SUCCESS, "failed to query table\n");
4079 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4080 ok(r == ERROR_SUCCESS, "failed to get column info\n");
4081
4082 sz = sizeof buf;
4083 r = MsiRecordGetStringA(rec, 1, buf, &sz);
4084 ok(r == ERROR_SUCCESS, "failed to get string\n");
4085 ok( 0 == strcmp("G255", buf), "wrong column type\n");
4086
4087 sz = sizeof buf;
4088 r = MsiRecordGetStringA(rec, 2, buf, &sz);
4089 ok(r == ERROR_SUCCESS, "failed to get string\n");
4090 ok( 0 == strcmp("j2", buf), "wrong column type\n");
4091
4092 MsiCloseHandle( rec );
4093 MsiViewClose( view );
4094 MsiCloseHandle( view );
4095
4096 /* query the table data */
4097 rec = 0;
4098 r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
4099 ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
4100 MsiCloseHandle( rec );
4101
4102 /* query the column data */
4103 rec = 0;
4104 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
4105 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4106 if (rec) MsiCloseHandle( rec );
4107
4108 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
4109 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
4110 if (rec) MsiCloseHandle( rec );
4111
4112 MsiCloseHandle( hdb );
4113 DeleteFileA(msifile);
4114 }
4115
4116 static void test_alter(void)
4117 {
4118 MSICONDITION cond;
4119 MSIHANDLE hdb = 0;
4120 const char *query;
4121 UINT r;
4122
4123 hdb = create_db();
4124 ok( hdb, "failed to create db\n");
4125
4126 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
4127 r = run_query(hdb, 0, query);
4128 ok(r == ERROR_SUCCESS, "failed to add table\n");
4129
4130 cond = MsiDatabaseIsTablePersistentA(hdb, "T");
4131 ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
4132
4133 query = "ALTER TABLE `T` HOLD";
4134 r = run_query(hdb, 0, query);
4135 ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
4136
4137 query = "ALTER TABLE `T` FREE";
4138 r = run_query(hdb, 0, query);
4139 ok(r == ERROR_SUCCESS, "failed to free table\n");
4140
4141 query = "ALTER TABLE `T` FREE";
4142 r = run_query(hdb, 0, query);
4143 ok(r == ERROR_SUCCESS, "failed to free table\n");
4144
4145 query = "ALTER TABLE `T` FREE";
4146 r = run_query(hdb, 0, query);
4147 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
4148
4149 query = "ALTER TABLE `T` HOLD";
4150 r = run_query(hdb, 0, query);
4151 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
4152
4153 /* table T is removed */
4154 query = "SELECT * FROM `T`";
4155 r = run_query(hdb, 0, query);
4156 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4157
4158 /* create the table again */
4159 query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
4160 r = run_query(hdb, 0, query);
4161 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4162
4163 /* up the ref count */
4164 query = "ALTER TABLE `U` HOLD";
4165 r = run_query(hdb, 0, query);
4166 ok(r == ERROR_SUCCESS, "failed to free table\n");
4167
4168 /* add column, no data type */
4169 query = "ALTER TABLE `U` ADD `C`";
4170 r = run_query(hdb, 0, query);
4171 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4172
4173 query = "ALTER TABLE `U` ADD `C` INTEGER";
4174 r = run_query(hdb, 0, query);
4175 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4176
4177 /* add column C again */
4178 query = "ALTER TABLE `U` ADD `C` INTEGER";
4179 r = run_query(hdb, 0, query);
4180 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4181
4182 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4183 r = run_query(hdb, 0, query);
4184 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4185
4186 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4187 r = run_query(hdb, 0, query);
4188 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4189
4190 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4191 r = run_query(hdb, 0, query);
4192 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4193
4194 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4195 r = run_query(hdb, 0, query);
4196 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4197
4198 query = "SELECT * FROM `U` WHERE `D` = 8";
4199 r = run_query(hdb, 0, query);
4200 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4201
4202 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4203 r = run_query(hdb, 0, query);
4204 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4205
4206 query = "ALTER COLUMN `D` FREE";
4207 r = run_query(hdb, 0, query);
4208 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4209
4210 /* drop the ref count */
4211 query = "ALTER TABLE `U` FREE";
4212 r = run_query(hdb, 0, query);
4213 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4214
4215 /* table is not empty */
4216 query = "SELECT * FROM `U`";
4217 r = run_query(hdb, 0, query);
4218 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4219
4220 /* column D is removed */
4221 query = "SELECT * FROM `U` WHERE `D` = 8";
4222 r = run_query(hdb, 0, query);
4223 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4224
4225 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4226 r = run_query(hdb, 0, query);
4227 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4228
4229 /* add the column again */
4230 query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4231 r = run_query(hdb, 0, query);
4232 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4233
4234 /* up the ref count */
4235 query = "ALTER TABLE `U` HOLD";
4236 r = run_query(hdb, 0, query);
4237 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4238
4239 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4240 r = run_query(hdb, 0, query);
4241 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4242
4243 query = "SELECT * FROM `U` WHERE `E` = 16";
4244 r = run_query(hdb, 0, query);
4245 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4246
4247 /* drop the ref count */
4248 query = "ALTER TABLE `U` FREE";
4249 r = run_query(hdb, 0, query);
4250 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4251
4252 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4253 r = run_query(hdb, 0, query);
4254 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4255
4256 query = "SELECT * FROM `U` WHERE `E` = 20";
4257 r = run_query(hdb, 0, query);
4258 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4259
4260 /* drop the ref count */
4261 query = "ALTER TABLE `U` FREE";
4262 r = run_query(hdb, 0, query);
4263 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4264
4265 /* table still exists */
4266 query = "SELECT * FROM `U`";
4267 r = run_query(hdb, 0, query);
4268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4269
4270 /* col E is removed */
4271 query = "SELECT * FROM `U` WHERE `E` = 20";
4272 r = run_query(hdb, 0, query);
4273 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4274
4275 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4276 r = run_query(hdb, 0, query);
4277 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4278
4279 /* drop the ref count once more */
4280 query = "ALTER TABLE `U` FREE";
4281 r = run_query(hdb, 0, query);
4282 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4283
4284 /* table still exists */
4285 query = "SELECT * FROM `U`";
4286 r = run_query(hdb, 0, query);
4287 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4288
4289 MsiCloseHandle( hdb );
4290 DeleteFileA(msifile);
4291 }
4292
4293 static void test_integers(void)
4294 {
4295 MSIHANDLE hdb = 0, view = 0, rec = 0;
4296 DWORD count, i;
4297 const char *query;
4298 UINT r;
4299
4300 /* just MsiOpenDatabase should not create a file */
4301 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4302 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4303
4304 /* create a table */
4305 query = "CREATE TABLE `integers` ( "
4306 "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4307 "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4308 "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4309 "PRIMARY KEY `one`)";
4310 r = MsiDatabaseOpenViewA(hdb, query, &view);
4311 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4312 r = MsiViewExecute(view, 0);
4313 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4314 r = MsiViewClose(view);
4315 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4316 r = MsiCloseHandle(view);
4317 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4318
4319 query = "SELECT * FROM `integers`";
4320 r = MsiDatabaseOpenViewA(hdb, query, &view);
4321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4322
4323 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4324 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4325 count = MsiRecordGetFieldCount(rec);
4326 ok(count == 8, "Expected 8, got %d\n", count);
4327 ok(check_record(rec, 1, "one"), "Expected one\n");
4328 ok(check_record(rec, 2, "two"), "Expected two\n");
4329 ok(check_record(rec, 3, "three"), "Expected three\n");
4330 ok(check_record(rec, 4, "four"), "Expected four\n");
4331 ok(check_record(rec, 5, "five"), "Expected five\n");
4332 ok(check_record(rec, 6, "six"), "Expected six\n");
4333 ok(check_record(rec, 7, "seven"), "Expected seven\n");
4334 ok(check_record(rec, 8, "eight"), "Expected eight\n");
4335 MsiCloseHandle(rec);
4336
4337 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4338 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4339 count = MsiRecordGetFieldCount(rec);
4340 ok(count == 8, "Expected 8, got %d\n", count);
4341 ok(check_record(rec, 1, "I2"), "Expected I2\n");
4342 ok(check_record(rec, 2, "I2"), "Expected I2\n");
4343 ok(check_record(rec, 3, "I2"), "Expected I2\n");
4344 ok(check_record(rec, 4, "I4"), "Expected I4\n");
4345 ok(check_record(rec, 5, "i2"), "Expected i2\n");
4346 ok(check_record(rec, 6, "i2"), "Expected i2\n");
4347 ok(check_record(rec, 7, "i2"), "Expected i2\n");
4348 ok(check_record(rec, 8, "i4"), "Expected i4\n");
4349 MsiCloseHandle(rec);
4350
4351 MsiViewClose(view);
4352 MsiCloseHandle(view);
4353
4354 /* insert values into it, NULL where NOT NULL is specified */
4355 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4356 "VALUES('', '', '', '', '', '', '', '')";
4357 r = MsiDatabaseOpenViewA(hdb, query, &view);
4358 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4359 r = MsiViewExecute(view, 0);
4360 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4361
4362 MsiViewClose(view);
4363 MsiCloseHandle(view);
4364
4365 query = "SELECT * FROM `integers`";
4366 r = do_query(hdb, query, &rec);
4367 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4368
4369 r = MsiRecordGetFieldCount(rec);
4370 ok(r == -1, "record count wrong: %d\n", r);
4371
4372 MsiCloseHandle(rec);
4373
4374 /* insert legitimate values into it */
4375 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4376 "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4377 r = MsiDatabaseOpenViewA(hdb, query, &view);
4378 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4379 r = MsiViewExecute(view, 0);
4380 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4381
4382 query = "SELECT * FROM `integers`";
4383 r = do_query(hdb, query, &rec);
4384 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4385
4386 r = MsiRecordGetFieldCount(rec);
4387 ok(r == 8, "record count wrong: %d\n", r);
4388
4389 i = MsiRecordGetInteger(rec, 1);
4390 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4391 i = MsiRecordGetInteger(rec, 3);
4392 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", i);
4393 i = MsiRecordGetInteger(rec, 2);
4394 ok(i == 2, "Expected 2, got %d\n", i);
4395 i = MsiRecordGetInteger(rec, 4);
4396 ok(i == 4, "Expected 4, got %d\n", i);
4397 i = MsiRecordGetInteger(rec, 5);
4398 ok(i == 5, "Expected 5, got %d\n", i);
4399 i = MsiRecordGetInteger(rec, 6);
4400 ok(i == 6, "Expected 6, got %d\n", i);
4401 i = MsiRecordGetInteger(rec, 7);
4402 ok(i == 7, "Expected 7, got %d\n", i);
4403 i = MsiRecordGetInteger(rec, 8);
4404 ok(i == 8, "Expected 8, got %d\n", i);
4405
4406 MsiCloseHandle(rec);
4407 MsiViewClose(view);
4408 MsiCloseHandle(view);
4409
4410 r = MsiDatabaseCommit(hdb);
4411 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4412
4413 r = MsiCloseHandle(hdb);
4414 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4415
4416 r = DeleteFileA(msifile);
4417 ok(r == TRUE, "file didn't exist after commit\n");
4418 }
4419
4420 static void test_update(void)
4421 {
4422 MSIHANDLE hdb = 0, view = 0, rec = 0;
4423 CHAR result[MAX_PATH];
4424 const char *query;
4425 DWORD size;
4426 UINT r;
4427
4428 /* just MsiOpenDatabase should not create a file */
4429 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4430 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4431
4432 /* create the Control table */
4433 query = "CREATE TABLE `Control` ( "
4434 "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4435 "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4436 "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4437 "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4438 r = MsiDatabaseOpenViewA(hdb, query, &view);
4439 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4440 r = MsiViewExecute(view, 0);
4441 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4442 r = MsiViewClose(view);
4443 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4444 r = MsiCloseHandle(view);
4445 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4446
4447 /* add a control */
4448 query = "INSERT INTO `Control` ( "
4449 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4450 "`Property`, `Text`, `Control_Next`, `Help` )"
4451 "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4452 r = MsiDatabaseOpenViewA(hdb, query, &view);
4453 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4454 r = MsiViewExecute(view, 0);
4455 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4456 r = MsiViewClose(view);
4457 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4458 r = MsiCloseHandle(view);
4459 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4460
4461 /* add a second control */
4462 query = "INSERT INTO `Control` ( "
4463 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4464 "`Property`, `Text`, `Control_Next`, `Help` )"
4465 "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4466 r = MsiDatabaseOpenViewA(hdb, query, &view);
4467 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4468 r = MsiViewExecute(view, 0);
4469 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4470 r = MsiViewClose(view);
4471 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4472 r = MsiCloseHandle(view);
4473 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4474
4475 /* add a third control */
4476 query = "INSERT INTO `Control` ( "
4477 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4478 "`Property`, `Text`, `Control_Next`, `Help` )"
4479 "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4480 r = MsiDatabaseOpenViewA(hdb, query, &view);
4481 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4482 r = MsiViewExecute(view, 0);
4483 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4484 r = MsiViewClose(view);
4485 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4486 r = MsiCloseHandle(view);
4487 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4488
4489 /* bad table */
4490 query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4491 r = MsiDatabaseOpenViewA(hdb, query, &view);
4492 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4493
4494 /* bad set column */
4495 query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4496 r = MsiDatabaseOpenViewA(hdb, query, &view);
4497 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4498
4499 /* bad where condition */
4500 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4501 r = MsiDatabaseOpenViewA(hdb, query, &view);
4502 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4503
4504 /* just the dialog_ specified */
4505 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4506 r = MsiDatabaseOpenViewA(hdb, query, &view);
4507 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4508 r = MsiViewExecute(view, 0);
4509 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4510 r = MsiViewClose(view);
4511 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4512 r = MsiCloseHandle(view);
4513 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4514
4515 /* check the modified text */
4516 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4517 r = MsiDatabaseOpenViewA(hdb, query, &view);
4518 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4519 r = MsiViewExecute(view, 0);
4520 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4521
4522 r = MsiViewFetch(view, &rec);
4523 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4524
4525 size = MAX_PATH;
4526 r = MsiRecordGetStringA(rec, 1, result, &size);
4527 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4528 ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4529
4530 MsiCloseHandle(rec);
4531
4532 r = MsiViewFetch(view, &rec);
4533 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4534
4535 size = MAX_PATH;
4536 r = MsiRecordGetStringA(rec, 1, result, &size);
4537 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4538 ok(!lstrlenA(result), "Expected an empty string, got %s\n", result);
4539
4540 MsiCloseHandle(rec);
4541
4542 r = MsiViewFetch(view, &rec);
4543 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4544
4545 r = MsiViewClose(view);
4546 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4547 r = MsiCloseHandle(view);
4548 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4549
4550 /* dialog_ and control specified */
4551 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4552 r = MsiDatabaseOpenViewA(hdb, query, &view);
4553 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4554 r = MsiViewExecute(view, 0);
4555 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4556 r = MsiViewClose(view);
4557 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4558 r = MsiCloseHandle(view);
4559 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4560
4561 /* check the modified text */
4562 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4563 r = MsiDatabaseOpenViewA(hdb, query, &view);
4564 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4565 r = MsiViewExecute(view, 0);
4566 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4567
4568 r = MsiViewFetch(view, &rec);
4569 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4570
4571 size = MAX_PATH;
4572 r = MsiRecordGetStringA(rec, 1, result, &size);
4573 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4574 ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4575
4576 MsiCloseHandle(rec);
4577
4578 r = MsiViewFetch(view, &rec);
4579 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4580
4581 size = MAX_PATH;
4582 r = MsiRecordGetStringA(rec, 1, result, &size);
4583 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4584 ok(!lstrlenA(result), "Expected an empty string, got %s\n", result);
4585
4586 MsiCloseHandle(rec);
4587
4588 r = MsiViewFetch(view, &rec);
4589 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4590
4591 r = MsiViewClose(view);
4592 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4593 r = MsiCloseHandle(view);
4594 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4595
4596 /* no where condition */
4597 query = "UPDATE `Control` SET `Text` = 'this is text'";
4598 r = MsiDatabaseOpenViewA(hdb, query, &view);
4599 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4600 r = MsiViewExecute(view, 0);
4601 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4602 r = MsiViewClose(view);
4603 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4604 r = MsiCloseHandle(view);
4605 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4606
4607 /* check the modified text */
4608 query = "SELECT `Text` FROM `Control`";
4609 r = MsiDatabaseOpenViewA(hdb, query, &view);
4610 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4611 r = MsiViewExecute(view, 0);
4612 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4613
4614 r = MsiViewFetch(view, &rec);
4615 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616
4617 size = MAX_PATH;
4618 r = MsiRecordGetStringA(rec, 1, result, &size);
4619 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4620 ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4621
4622 MsiCloseHandle(rec);
4623
4624 r = MsiViewFetch(view, &rec);
4625 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4626
4627 size = MAX_PATH;
4628 r = MsiRecordGetStringA(rec, 1, result, &size);
4629 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4630 ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4631
4632 MsiCloseHandle(rec);
4633
4634 r = MsiViewFetch(view, &rec);
4635 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4636
4637 size = MAX_PATH;
4638 r = MsiRecordGetStringA(rec, 1, result, &size);
4639 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4640 ok(!lstrcmpA(result, "this is text"), "Expected `this is text`, got %s\n", result);
4641
4642 MsiCloseHandle(rec);
4643
4644 r = MsiViewFetch(view, &rec);
4645 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4646
4647 r = MsiViewClose(view);
4648 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4649 r = MsiCloseHandle(view);
4650 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4651
4652 query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4653 "`Orange` CHAR(72), `Pear` INT PRIMARY KEY `Banana`)";
4654 r = run_query(hdb, 0, query);
4655 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4656
4657 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4658 "VALUES('one', 'two', 3)";
4659 r = run_query(hdb, 0, query);
4660 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4661
4662 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4663 "VALUES('three', 'four', 5)";
4664 r = run_query(hdb, 0, query);
4665 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4666
4667 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4668 "VALUES('six', 'two', 7)";
4669 r = run_query(hdb, 0, query);
4670 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4671
4672 rec = MsiCreateRecord(2);
4673 MsiRecordSetInteger(rec, 1, 8);
4674 MsiRecordSetStringA(rec, 2, "two");
4675
4676 query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4677 r = run_query(hdb, rec, query);
4678 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4679
4680 MsiCloseHandle(rec);
4681
4682 query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4683 r = MsiDatabaseOpenViewA(hdb, query, &view);
4684 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4685 r = MsiViewExecute(view, 0);
4686 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4687
4688 r = MsiViewFetch(view, &rec);
4689 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4690
4691 r = MsiRecordGetInteger(rec, 1);
4692 ok(r == 8, "Expected 8, got %d\n", r);
4693
4694 MsiCloseHandle(rec);
4695
4696 r = MsiViewFetch(view, &rec);
4697 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4698
4699 r = MsiRecordGetInteger(rec, 1);
4700 ok(r == 8, "Expected 8, got %d\n", r);
4701
4702 MsiCloseHandle(rec);
4703
4704 r = MsiViewFetch(view, &rec);
4705 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4706
4707 r = MsiRecordGetInteger(rec, 1);
4708 ok(r == 5, "Expected 5, got %d\n", r);
4709
4710 MsiCloseHandle(rec);
4711
4712 r = MsiViewFetch(view, &rec);
4713 ok(r == ERROR_NO_MORE_ITEMS, "Expectd ERROR_NO_MORE_ITEMS, got %d\n", r);
4714
4715 MsiViewClose(view);
4716 MsiCloseHandle(view);
4717
4718 r = MsiDatabaseCommit(hdb);
4719 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4720 r = MsiCloseHandle(hdb);
4721 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4722
4723 DeleteFileA(msifile);
4724 }
4725
4726 static void test_special_tables(void)
4727 {
4728 const char *query;
4729 MSIHANDLE hdb = 0;
4730 UINT r;
4731
4732 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4733 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4734
4735 query = "CREATE TABLE `_Properties` ( "
4736 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4737 r = run_query(hdb, 0, query);
4738 ok(r == ERROR_SUCCESS, "failed to create table\n");
4739
4740 query = "CREATE TABLE `_Storages` ( "
4741 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4742 r = run_query(hdb, 0, query);
4743 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4744
4745 query = "CREATE TABLE `_Streams` ( "
4746 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4747 r = run_query(hdb, 0, query);
4748 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4749
4750 query = "CREATE TABLE `_Tables` ( "
4751 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4752 r = run_query(hdb, 0, query);
4753 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4754
4755 query = "CREATE TABLE `_Columns` ( "
4756 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4757 r = run_query(hdb, 0, query);
4758 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4759
4760 r = MsiCloseHandle(hdb);
4761 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4762 }
4763
4764 static void test_tables_order(void)
4765 {
4766 const char *query;
4767 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4768 UINT r;
4769 char buffer[100];
4770 DWORD sz;
4771
4772 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4773 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4774
4775 query = "CREATE TABLE `foo` ( "
4776 "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4777 r = run_query(hdb, 0, query);
4778 ok(r == ERROR_SUCCESS, "failed to create table\n");
4779
4780 query = "CREATE TABLE `bar` ( "
4781 "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4782 r = run_query(hdb, 0, query);
4783 ok(r == ERROR_SUCCESS, "failed to create table\n");
4784
4785 query = "CREATE TABLE `baz` ( "
4786 "`bar` INT NOT NULL, "
4787 "`baz` INT NOT NULL, "
4788 "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4789 r = run_query(hdb, 0, query);
4790 ok(r == ERROR_SUCCESS, "failed to create table\n");
4791
4792 /* The names of the tables in the _Tables table must
4793 be in the same order as these names are created in
4794 the strings table. */
4795 query = "SELECT * FROM `_Tables`";
4796 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4797 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4798 r = MsiViewExecute(hview, 0);
4799 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4800
4801 r = MsiViewFetch(hview, &hrec);
4802 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4803 sz = sizeof(buffer);
4804 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4805 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4806 ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4807 r = MsiCloseHandle(hrec);
4808 ok(r == ERROR_SUCCESS, "failed to close record\n");
4809
4810 r = MsiViewFetch(hview, &hrec);
4811 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4812 sz = sizeof(buffer);
4813 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4814 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4815 ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4816 r = MsiCloseHandle(hrec);
4817 ok(r == ERROR_SUCCESS, "failed to close record\n");
4818
4819 r = MsiViewFetch(hview, &hrec);
4820 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4821 sz = sizeof(buffer);
4822 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4823 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4824 ok(!lstrcmpA(buffer, "bar"), "Expected bar, got %s\n", buffer);
4825 r = MsiCloseHandle(hrec);
4826 ok(r == ERROR_SUCCESS, "failed to close record\n");
4827
4828 r = MsiViewClose(hview);
4829 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4830 r = MsiCloseHandle(hview);
4831 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4832
4833 /* The names of the tables in the _Columns table must
4834 be in the same order as these names are created in
4835 the strings table. */
4836 query = "SELECT * FROM `_Columns`";
4837 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4838 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4839 r = MsiViewExecute(hview, 0);
4840 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4841
4842 r = MsiViewFetch(hview, &hrec);
4843 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4844 sz = sizeof(buffer);
4845 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4846 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4847 ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4848 sz = sizeof(buffer);
4849 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4850 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4851 ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4852 r = MsiCloseHandle(hrec);
4853 ok(r == ERROR_SUCCESS, "failed to close record\n");
4854
4855 r = MsiViewFetch(hview, &hrec);
4856 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4857 sz = sizeof(buffer);
4858 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4859 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4860 ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4861 sz = sizeof(buffer);
4862 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4863 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4864 ok(!lstrcmpA(buffer, "bar"), "Expected bar, got %s\n", buffer);
4865 r = MsiCloseHandle(hrec);
4866 ok(r == ERROR_SUCCESS, "failed to close record\n");
4867
4868 r = MsiViewFetch(hview, &hrec);
4869 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4870 sz = sizeof(buffer);
4871 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4872 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4873 ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4874 sz = sizeof(buffer);
4875 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4876 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4877 ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4878 r = MsiCloseHandle(hrec);
4879 ok(r == ERROR_SUCCESS, "failed to close record\n");
4880
4881 r = MsiViewFetch(hview, &hrec);
4882 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4883 sz = sizeof(buffer);
4884 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4885 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4886 ok(!lstrcmpA(buffer, "baz"), "Expected baz, got %s\n", buffer);
4887 sz = sizeof(buffer);
4888 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4889 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4890 ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4891 r = MsiCloseHandle(hrec);
4892 ok(r == ERROR_SUCCESS, "failed to close record\n");
4893
4894 r = MsiViewFetch(hview, &hrec);
4895 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4896 sz = sizeof(buffer);
4897 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4898 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4899 ok(!lstrcmpA(buffer, "bar"), "Expected bar, got %s\n", buffer);
4900 sz = sizeof(buffer);
4901 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
4902 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4903 ok(!lstrcmpA(buffer, "foo"), "Expected foo, got %s\n", buffer);
4904 r = MsiCloseHandle(hrec);
4905 ok(r == ERROR_SUCCESS, "failed to close record\n");
4906
4907 r = MsiViewClose(hview);
4908 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4909 r = MsiCloseHandle(hview);
4910 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4911
4912 r = MsiCloseHandle(hdb);
4913 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4914
4915 DeleteFileA(msifile);
4916 }
4917
4918 static void test_rows_order(void)
4919 {
4920 const char *query;
4921 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4922 UINT r;
4923 char buffer[100];
4924 DWORD sz;
4925
4926 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4927 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4928
4929 query = "CREATE TABLE `foo` ( "
4930 "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4931 r = run_query(hdb, 0, query);
4932 ok(r == ERROR_SUCCESS, "failed to create table\n");
4933
4934 r = run_query(hdb, 0, "INSERT INTO `foo` "
4935 "( `bar` ) VALUES ( 'A' )");
4936 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4937
4938 r = run_query(hdb, 0, "INSERT INTO `foo` "
4939 "( `bar` ) VALUES ( 'B' )");
4940 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4941
4942 r = run_query(hdb, 0, "INSERT INTO `foo` "
4943 "( `bar` ) VALUES ( 'C' )");
4944 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4945
4946 r = run_query(hdb, 0, "INSERT INTO `foo` "
4947 "( `bar` ) VALUES ( 'D' )");
4948 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4949
4950 r = run_query(hdb, 0, "INSERT INTO `foo` "
4951 "( `bar` ) VALUES ( 'E' )");
4952 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4953
4954 r = run_query(hdb, 0, "INSERT INTO `foo` "
4955 "( `bar` ) VALUES ( 'F' )");
4956 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4957
4958 query = "CREATE TABLE `bar` ( "
4959 "`foo` LONGCHAR NOT NULL, "
4960 "`baz` LONGCHAR NOT NULL "
4961 "PRIMARY KEY `foo` )";
4962 r = run_query(hdb, 0, query);
4963 ok(r == ERROR_SUCCESS, "failed to create table\n");
4964
4965 r = run_query(hdb, 0, "INSERT INTO `bar` "
4966 "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4967 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4968
4969 r = run_query(hdb, 0, "INSERT INTO `bar` "
4970 "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4971 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4972
4973 r = run_query(hdb, 0, "INSERT INTO `bar` "
4974 "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4975 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4976
4977 r = run_query(hdb, 0, "INSERT INTO `bar` "
4978 "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4979 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4980
4981 /* The rows of the table must be ordered by the column values of
4982 each row. For strings, the column value is the string id
4983 in the string table. */
4984
4985 query = "SELECT * FROM `bar`";
4986 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4987 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4988 r = MsiViewExecute(hview, 0);
4989 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4990
4991 r = MsiViewFetch(hview, &hrec);
4992 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4993 sz = sizeof(buffer);
4994 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4995 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4996 ok(!lstrcmpA(buffer, "A"), "Expected A, got %s\n", buffer);
4997 sz = sizeof(buffer);
4998 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
4999 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5000 ok(!lstrcmpA(buffer, "B"), "Expected B, got %s\n", buffer);
5001 r = MsiCloseHandle(hrec);
5002 ok(r == ERROR_SUCCESS, "failed to close record\n");
5003
5004 r = MsiViewFetch(hview, &hrec);
5005 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5006 sz = sizeof(buffer);
5007 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5008 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5009 ok(!lstrcmpA(buffer, "C"), "Expected E, got %s\n", buffer);
5010 sz = sizeof(buffer);
5011 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5012 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5013 ok(!lstrcmpA(buffer, "E"), "Expected E, got %s\n", buffer);
5014 r = MsiCloseHandle(hrec);
5015 ok(r == ERROR_SUCCESS, "failed to close record\n");
5016
5017 r = MsiViewFetch(hview, &hrec);
5018 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5019 sz = sizeof(buffer);
5020 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5021 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5022 ok(!lstrcmpA(buffer, "D"), "Expected D, got %s\n", buffer);
5023 sz = sizeof(buffer);
5024 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5025 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5026 ok(!lstrcmpA(buffer, "E"), "Expected E, got %s\n", buffer);
5027 r = MsiCloseHandle(hrec);
5028 ok(r == ERROR_SUCCESS, "failed to close record\n");
5029
5030 r = MsiViewFetch(hview, &hrec);
5031 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5032 sz = sizeof(buffer);
5033 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5034 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5035 ok(!lstrcmpA(buffer, "F"), "Expected F, got %s\n", buffer);
5036 sz = sizeof(buffer);
5037 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5038 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5039 ok(!lstrcmpA(buffer, "A"), "Expected A, got %s\n", buffer);
5040 r = MsiCloseHandle(hrec);
5041 ok(r == ERROR_SUCCESS, "failed to close record\n");
5042
5043 r = MsiViewClose(hview);
5044 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5045 r = MsiCloseHandle(hview);
5046 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5047
5048 r = MsiCloseHandle(hdb);
5049 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5050
5051 DeleteFileA(msifile);
5052 }
5053
5054 static void test_collation(void)
5055 {
5056 static const WCHAR query1[] =
5057 {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5058 '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5059 '(','\'','a',0x30a,'\'',',','\'','C','\'',')',0};
5060 static const WCHAR query2[] =
5061 {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','b','a','r','`',' ',
5062 '(','`','f','o','o','`',',','`','b','a','z','`',')',' ','V','A','L','U','E','S',' ',
5063 '(','\'',0xe5,'\'',',','\'','D','\'',')',0};
5064 static const WCHAR query3[] =
5065 {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','b','a','z','`',' ',
5066 '(',' ','`','a',0x30a,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',',',
5067 ' ','`',0xe5,'`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ','N','U','L','L',' ',
5068 'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','a',0x30a,'`',')',0};
5069 static const WCHAR query4[] =
5070 {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','a',0x30a,'`',' ',
5071 '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5072 'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5073 static const WCHAR query5[] =
5074 {'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`',0xe5,'`',' ',
5075 '(',' ','`','f','o','o','`',' ','L','O','N','G','C','H','A','R',' ','N','O','T',' ',
5076 'N','U','L','L',' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','f','o','o','`',')',0};
5077 static const WCHAR query6[] =
5078 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','b','a','r','`',' ','W','H','E','R','E',
5079 ' ','`','f','o','o','`',' ','=','\'',0xe5,'\'',0};
5080 static const WCHAR letter_C[] = {'C',0};
5081 static const WCHAR letter_D[] = {'D',0};
5082 static const WCHAR letter_a_ring[] = {'a',0x30a,0};
5083 static const WCHAR letter_a_with_ring[] = {0xe5,0};
5084 const char *query;
5085 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5086 UINT r;
5087 char buffer[100];
5088 WCHAR bufferW[100];
5089 DWORD sz;
5090
5091 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5092 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5093
5094 query = "CREATE TABLE `bar` ( "
5095 "`foo` LONGCHAR NOT NULL, "
5096 "`baz` LONGCHAR NOT NULL "
5097 "PRIMARY KEY `foo` )";
5098 r = run_query(hdb, 0, query);
5099 ok(r == ERROR_SUCCESS, "failed to create table\n");
5100
5101 r = run_query(hdb, 0, query);
5102 ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
5103
5104 r = run_query(hdb, 0, "INSERT INTO `bar` "
5105 "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
5106 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5107
5108 r = run_query(hdb, 0, "INSERT INTO `bar` "
5109 "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
5110 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5111
5112 r = run_queryW(hdb, 0, query1);
5113 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5114
5115 r = run_queryW(hdb, 0, query2);
5116 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
5117
5118 r = run_queryW(hdb, 0, query3);
5119 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5120
5121 r = run_queryW(hdb, 0, query4);
5122 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5123
5124 r = run_queryW(hdb, 0, query5);
5125 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
5126
5127 query = "SELECT * FROM `bar`";
5128 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5129 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5130 r = MsiViewExecute(hview, 0);
5131 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5132
5133 r = MsiViewFetch(hview, &hrec);
5134 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5135 sz = sizeof(buffer);
5136 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5137 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5138 ok(!lstrcmpA(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
5139 sz = sizeof(buffer);
5140 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5141 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5142 ok(!lstrcmpA(buffer, "A"), "Expected A, got '%s'\n", buffer);
5143 MsiCloseHandle(hrec);
5144
5145 r = MsiViewFetch(hview, &hrec);
5146 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5147 sz = sizeof(buffer);
5148 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
5149 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5150 ok(!lstrcmpA(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
5151 sz = sizeof(buffer);
5152 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5153 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5154 ok(!lstrcmpA(buffer, "B"), "Expected B, got '%s'\n", buffer);
5155 MsiCloseHandle(hrec);
5156
5157 r = MsiViewFetch(hview, &hrec);
5158 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5159 sz = sizeof(bufferW) / sizeof(bufferW[0]);
5160 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5161 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5162 ok(!memcmp(bufferW, letter_a_ring, sizeof(letter_a_ring)),
5163 "Expected %s, got %s\n", wine_dbgstr_w(letter_a_ring), wine_dbgstr_w(bufferW));
5164 sz = sizeof(bufferW) / sizeof(bufferW[0]);
5165 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5166 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5167 ok(!lstrcmpW(bufferW, letter_C), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
5168 MsiCloseHandle(hrec);
5169
5170 r = MsiViewFetch(hview, &hrec);
5171 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5172 sz = sizeof(bufferW) / sizeof(bufferW[0]);
5173 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5174 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5175 ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5176 "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5177 sz = sizeof(bufferW) / sizeof(bufferW[0]);
5178 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5179 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5180 ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5181 MsiCloseHandle(hrec);
5182
5183 r = MsiViewClose(hview);
5184 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5185 r = MsiCloseHandle(hview);
5186 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5187
5188 r = MsiDatabaseOpenViewW(hdb, query6, &hview);
5189 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5190 r = MsiViewExecute(hview, 0);
5191 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5192
5193 r = MsiViewFetch(hview, &hrec);
5194 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5195 sz = sizeof(bufferW) / sizeof(bufferW[0]);
5196 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
5197 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5198 ok(!memcmp(bufferW, letter_a_with_ring, sizeof(letter_a_with_ring)),
5199 "Expected %s, got %s\n", wine_dbgstr_w(letter_a_with_ring), wine_dbgstr_w(bufferW));
5200 sz = sizeof(bufferW) / sizeof(bufferW[0]);
5201 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
5202 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5203 ok(!lstrcmpW(bufferW, letter_D), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
5204 MsiCloseHandle(hrec);
5205
5206 r = MsiViewFetch(hview, &hrec);
5207 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
5208
5209 r = MsiViewClose(hview);
5210 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5211 r = MsiCloseHandle(hview);
5212 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5213
5214 r = MsiCloseHandle(hdb);
5215 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5216
5217 DeleteFileA(msifile);
5218 }
5219
5220 static void test_select_markers(void)
5221 {
5222 MSIHANDLE hdb = 0, rec, view, res;
5223 LPCSTR query;
5224 UINT r;
5225 DWORD size;
5226 CHAR buf[MAX_PATH];
5227
5228 hdb = create_db();
5229 ok( hdb, "failed to create db\n");
5230
5231 r = run_query(hdb, 0,
5232 "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
5233 ok(r == S_OK, "cannot create table: %d\n", r);
5234
5235 r = run_query(hdb, 0, "INSERT INTO `Table` "
5236 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
5237 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5238
5239 r = run_query(hdb, 0, "INSERT INTO `Table` "
5240 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
5241 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5242
5243 r = run_query(hdb, 0, "INSERT INTO `Table` "
5244 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
5245 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5246
5247 r = run_query(hdb, 0, "INSERT INTO `Table` "
5248 "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
5249 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
5250
5251 rec = MsiCreateRecord(2);
5252 MsiRecordSetStringA(rec, 1, "apple");
5253 MsiRecordSetStringA(rec, 2, "two");
5254
5255 query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
5256 r = MsiDatabaseOpenViewA(hdb, query, &view);
5257 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5258
5259 r = MsiViewExecute(view, rec);
5260 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5261
5262 r = MsiViewFetch(view, &res);
5263 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5264
5265 size = MAX_PATH;
5266 r = MsiRecordGetStringA(res, 1, buf, &size);
5267 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5268 ok(!lstrcmpA(buf, "apple"), "Expected apple, got %s\n", buf);
5269
5270 size = MAX_PATH;
5271 r = MsiRecordGetStringA(res, 2, buf, &size);
5272 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5273 ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
5274
5275 r = MsiRecordGetInteger(res, 3);
5276 ok(r == 1, "Expected 1, got %d\n", r);
5277
5278 MsiCloseHandle(res);
5279
5280 r = MsiViewFetch(view, &res);
5281 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5282
5283 size = MAX_PATH;
5284 r = MsiRecordGetStringA(res, 1, buf, &size);
5285 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5286 ok(!lstrcmpA(buf, "apple"), "Expected apple, got %s\n", buf);
5287
5288 size = MAX_PATH;
5289 r = MsiRecordGetStringA(res, 2, buf, &size);
5290 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5291 ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
5292
5293 r = MsiRecordGetInteger(res, 3);
5294 ok(r == 2, "Expected 2, got %d\n", r);
5295
5296 MsiCloseHandle(res);
5297
5298 r = MsiViewFetch(view, &res);
5299 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5300
5301 MsiCloseHandle(rec);
5302 MsiViewClose(view);
5303 MsiCloseHandle(view);
5304
5305 rec = MsiCreateRecord(2);
5306 MsiRecordSetStringA(rec, 1, "one");
5307 MsiRecordSetInteger(rec, 2, 1);
5308
5309 query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
5310 r = MsiDatabaseOpenViewA(hdb, query, &view);
5311 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5312 r = MsiViewExecute(view, rec);
5313 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5314
5315 r = MsiViewFetch(view, &res);
5316 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5317
5318 size = MAX_PATH;
5319 r = MsiRecordGetStringA(res, 1, buf, &size);
5320 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5321 ok(!lstrcmpA(buf, "apple"), "Expected apple, got %s\n", buf);
5322
5323 size = MAX_PATH;
5324 r = MsiRecordGetStringA(res, 2, buf, &size);
5325 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5326 ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
5327
5328 r = MsiRecordGetInteger(res, 3);
5329 ok(r == 2, "Expected 2, got %d\n", r);
5330
5331 MsiCloseHandle(res);
5332
5333 r = MsiViewFetch(view, &res);
5334 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5335
5336 size = MAX_PATH;
5337 r = MsiRecordGetStringA(res, 1, buf, &size);
5338 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5339 ok(!lstrcmpA(buf, "banana"), "Expected banana, got %s\n", buf);
5340
5341 size = MAX_PATH;
5342 r = MsiRecordGetStringA(res, 2, buf, &size);
5343 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5344 ok(!lstrcmpA(buf, "three"), "Expected three, got %s\n", buf);
5345
5346 r = MsiRecordGetInteger(res, 3);
5347 ok(r == 3, "Expected 3, got %d\n", r);
5348
5349 MsiCloseHandle(res);
5350
5351 r = MsiViewFetch(view, &res);
5352 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5353
5354 MsiCloseHandle(rec);
5355 MsiViewClose(view);
5356 MsiCloseHandle(view);
5357 MsiCloseHandle(hdb);
5358 DeleteFileA(msifile);
5359 }
5360
5361 static void test_viewmodify_update(void)
5362 {
5363 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5364 UINT i, test_max, offset, count;
5365 const char *query;
5366 UINT r;
5367
5368 DeleteFileA(msifile);
5369
5370 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5371 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5372
5373 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5374 r = run_query( hdb, 0, query );
5375 ok(r == ERROR_SUCCESS, "query failed\n");
5376
5377 query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
5378 r = run_query( hdb, 0, query );
5379 ok(r == ERROR_SUCCESS, "query failed\n");
5380
5381 query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5382 r = run_query( hdb, 0, query );
5383 ok(r == ERROR_SUCCESS, "query failed\n");
5384
5385 query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5386 r = run_query( hdb, 0, query );
5387 ok(r == ERROR_SUCCESS, "query failed\n");
5388
5389 query = "SELECT `B` FROM `table`";
5390 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5391 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5392 r = MsiViewExecute(hview, 0);
5393 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5394 r = MsiViewFetch(hview, &hrec);
5395 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5396
5397 r = MsiRecordSetInteger(hrec, 1, 0);
5398 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5399
5400 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5401 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5402
5403 r = MsiCloseHandle(hrec);
5404 ok(r == ERROR_SUCCESS, "failed to close record\n");
5405
5406 r = MsiViewClose(hview);
5407 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5408 r = MsiCloseHandle(hview);
5409 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5410
5411 query = "SELECT * FROM `table`";
5412 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5413 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5414 r = MsiViewExecute(hview, 0);
5415 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5416 r = MsiViewFetch(hview, &hrec);
5417 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5418
5419 r = MsiRecordGetInteger(hrec, 1);
5420 ok(r == 1, "Expected 1, got %d\n", r);
5421 r = MsiRecordGetInteger(hrec, 2);
5422 ok(r == 0, "Expected 0, got %d\n", r);
5423
5424 r = MsiCloseHandle(hrec);
5425 ok(r == ERROR_SUCCESS, "failed to close record\n");
5426
5427 r = MsiViewFetch(hview, &hrec);
5428 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5429
5430 r = MsiRecordGetInteger(hrec, 1);
5431 ok(r == 3, "Expected 3, got %d\n", r);
5432 r = MsiRecordGetInteger(hrec, 2);
5433 ok(r == 4, "Expected 4, got %d\n", r);
5434
5435 r = MsiCloseHandle(hrec);
5436 ok(r == ERROR_SUCCESS, "failed to close record\n");
5437
5438 r = MsiViewFetch(hview, &hrec);
5439 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5440
5441 r = MsiRecordGetInteger(hrec, 1);
5442 ok(r == 5, "Expected 5, got %d\n", r);
5443 r = MsiRecordGetInteger(hrec, 2);
5444 ok(r == 6, "Expected 6, got %d\n", r);
5445
5446 r = MsiCloseHandle(hrec);
5447 ok(r == ERROR_SUCCESS, "failed to close record\n");
5448
5449 r = MsiViewFetch(hview, &hrec);
5450 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5451
5452 r = MsiViewClose(hview);
5453 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5454 r = MsiCloseHandle(hview);
5455 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5456
5457 /* loop through all elements */
5458 query = "SELECT `B` FROM `table`";
5459 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5460 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5461 r = MsiViewExecute(hview, 0);
5462 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5463
5464 while (TRUE)
5465 {
5466 r = MsiViewFetch(hview, &hrec);
5467 if (r != ERROR_SUCCESS)
5468 break;
5469
5470 r = MsiRecordSetInteger(hrec, 1, 0);
5471 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5472
5473 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5474 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5475
5476 r = MsiCloseHandle(hrec);
5477 ok(r == ERROR_SUCCESS, "failed to close record\n");
5478 }
5479
5480 r = MsiViewClose(hview);
5481 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5482 r = MsiCloseHandle(hview);
5483 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5484
5485 query = "SELECT * FROM `table`";
5486 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5487 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5488 r = MsiViewExecute(hview, 0);
5489 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5490 r = MsiViewFetch(hview, &hrec);
5491 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5492
5493 r = MsiRecordGetInteger(hrec, 1);
5494 ok(r == 1, "Expected 1, got %d\n", r);
5495 r = MsiRecordGetInteger(hrec, 2);
5496 ok(r == 0, "Expected 0, got %d\n", r);
5497
5498 r = MsiCloseHandle(hrec);
5499 ok(r == ERROR_SUCCESS, "failed to close record\n");
5500
5501 r = MsiViewFetch(hview, &hrec);
5502 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5503
5504 r = MsiRecordGetInteger(hrec, 1);
5505 ok(r == 3, "Expected 3, got %d\n", r);
5506 r = MsiRecordGetInteger(hrec, 2);
5507 ok(r == 0, "Expected 0, got %d\n", r);
5508
5509 r = MsiCloseHandle(hrec);
5510 ok(r == ERROR_SUCCESS, "failed to close record\n");
5511
5512 r = MsiViewFetch(hview, &hrec);
5513 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5514
5515 r = MsiRecordGetInteger(hrec, 1);
5516 ok(r == 5, "Expected 5, got %d\n", r);
5517 r = MsiRecordGetInteger(hrec, 2);
5518 ok(r == 0, "Expected 0, got %d\n", r);
5519
5520 r = MsiCloseHandle(hrec);
5521 ok(r == ERROR_SUCCESS, "failed to close record\n");
5522
5523 r = MsiViewFetch(hview, &hrec);
5524 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5525
5526 r = MsiViewClose(hview);
5527 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5528 r = MsiCloseHandle(hview);
5529 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5530
5531 query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5532 r = run_query( hdb, 0, query );
5533 ok(r == ERROR_SUCCESS, "query failed\n");
5534
5535 query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5536 r = MsiDatabaseOpenViewA( hdb, query, &hview );
5537 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5538
5539 test_max = 100;
5540 offset = 1234;
5541 for(i = 0; i < test_max; i++)
5542 {
5543
5544 hrec = MsiCreateRecord( 2 );
5545 MsiRecordSetInteger( hrec, 1, test_max - i );
5546 MsiRecordSetInteger( hrec, 2, i );
5547
5548 r = MsiViewExecute( hview, hrec );
5549 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5550
5551 r = MsiCloseHandle( hrec );
5552 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5553 }
5554
5555 r = MsiViewClose( hview );
5556 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5557 r = MsiCloseHandle( hview );
5558 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5559
5560 /* Update. */
5561 query = "SELECT * FROM `table2` ORDER BY `B`";
5562 r = MsiDatabaseOpenViewA( hdb, query, &hview);
5563 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5564 r = MsiViewExecute( hview, 0 );
5565 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5566
5567 count = 0;
5568 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5569 {
5570 UINT b = MsiRecordGetInteger( hrec, 2 );
5571
5572 r = MsiRecordSetInteger( hrec, 2, b + offset);
5573 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5574
5575 r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5576 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5577
5578 r = MsiCloseHandle(hrec);
5579 ok(r == ERROR_SUCCESS, "failed to close record\n");
5580 count++;
5581 }
5582 ok(count == test_max, "Got count %d\n", count);
5583
5584 r = MsiViewClose(hview);
5585 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5586 r = MsiCloseHandle(hview);
5587 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5588
5589 /* Recheck. */
5590 query = "SELECT * FROM `table2` ORDER BY `B`";
5591 r = MsiDatabaseOpenViewA( hdb, query, &hview);
5592 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5593 r = MsiViewExecute( hview, 0 );
5594 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5595
5596 count = 0;
5597 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5598 {
5599 UINT a = MsiRecordGetInteger( hrec, 1 );
5600 UINT b = MsiRecordGetInteger( hrec, 2 );
5601 ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5602 a, b, test_max - a + offset, b);
5603
5604 r = MsiCloseHandle(hrec);
5605 ok(r == ERROR_SUCCESS, "failed to close record\n");
5606 count++;
5607 }
5608 ok(count == test_max, "Got count %d\n", count);
5609
5610 r = MsiViewClose(hview);
5611 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5612 r = MsiCloseHandle(hview);
5613 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5614
5615 r = MsiCloseHandle( hdb );
5616 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5617 }
5618
5619 static void test_viewmodify_assign(void)
5620 {
5621 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5622 const char *query;
5623 UINT r;
5624
5625 /* setup database */
5626 DeleteFileA(msifile);
5627
5628 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5629 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5630
5631 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5632 r = run_query( hdb, 0, query );
5633 ok(r == ERROR_SUCCESS, "query failed\n");
5634
5635 /* assign to view, new primary key */
5636 query = "SELECT * FROM `table`";
5637 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5638 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5639 r = MsiViewExecute(hview, 0);
5640 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5641
5642 hrec = MsiCreateRecord(2);
5643 ok(hrec != 0, "MsiCreateRecord failed\n");
5644
5645 r = MsiRecordSetInteger(hrec, 1, 1);
5646 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5647 r = MsiRecordSetInteger(hrec, 2, 2);
5648 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5649
5650 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5651 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5652
5653 r = MsiCloseHandle(hrec);
5654 ok(r == ERROR_SUCCESS, "failed to close record\n");
5655
5656 r = MsiViewClose(hview);
5657 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5658 r = MsiCloseHandle(hview);
5659 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5660
5661 query = "SELECT * FROM `table`";
5662 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5663 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5664 r = MsiViewExecute(hview, 0);
5665 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5666 r = MsiViewFetch(hview, &hrec);
5667 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5668
5669 r = MsiRecordGetInteger(hrec, 1);
5670 ok(r == 1, "Expected 1, got %d\n", r);
5671 r = MsiRecordGetInteger(hrec, 2);
5672 ok(r == 2, "Expected 2, got %d\n", r);
5673
5674 r = MsiCloseHandle(hrec);
5675 ok(r == ERROR_SUCCESS, "failed to close record\n");
5676
5677 r = MsiViewFetch(hview, &hrec);
5678 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5679
5680 r = MsiViewClose(hview);
5681 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5682 r = MsiCloseHandle(hview);
5683 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5684
5685 /* assign to view, primary key matches */
5686 query = "SELECT * FROM `table`";
5687 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5688 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5689 r = MsiViewExecute(hview, 0);
5690 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5691
5692 hrec = MsiCreateRecord(2);
5693 ok(hrec != 0, "MsiCreateRecord failed\n");
5694
5695 r = MsiRecordSetInteger(hrec, 1, 1);
5696 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5697 r = MsiRecordSetInteger(hrec, 2, 4);
5698 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5699
5700 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5701 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5702
5703 r = MsiCloseHandle(hrec);
5704 ok(r == ERROR_SUCCESS, "failed to close record\n");
5705
5706 r = MsiViewClose(hview);
5707 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5708 r = MsiCloseHandle(hview);
5709 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5710
5711 query = "SELECT * FROM `table`";
5712 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5713 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5714 r = MsiViewExecute(hview, 0);
5715 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5716 r = MsiViewFetch(hview, &hrec);
5717 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5718
5719 r = MsiRecordGetInteger(hrec, 1);
5720 ok(r == 1, "Expected 1, got %d\n", r);
5721 r = MsiRecordGetInteger(hrec, 2);
5722 ok(r == 4, "Expected 4, got %d\n", r);
5723
5724 r = MsiCloseHandle(hrec);
5725 ok(r == ERROR_SUCCESS, "failed to close record\n");
5726
5727 r = MsiViewFetch(hview, &hrec);
5728 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5729
5730 r = MsiViewClose(hview);
5731 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5732 r = MsiCloseHandle(hview);
5733 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5734
5735 /* close database */
5736 r = MsiCloseHandle( hdb );
5737 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5738 }
5739
5740 static const WCHAR data10[] = { /* MOO */
5741 0x8001, 0x000b,
5742 };
5743 static const WCHAR data11[] = { /* AAR */
5744 0x8002, 0x8005,
5745 0x000c, 0x000f,
5746 };
5747 static const char data12[] = /* _StringData */
5748 "MOOABAARCDonetwofourfive";
5749 static const WCHAR data13[] = { /* _StringPool */
5750 /* len, refs */
5751 0, 0, /* string 0 '' */
5752 0, 0, /* string 1 '' */
5753 0, 0, /* string 2 '' */
5754 0, 0, /* string 3 '' */
5755 0, 0, /* string 4 '' */
5756 3, 3, /* string 5 'MOO' */
5757 1, 1, /* string 6 'A' */
5758 1, 1, /* string 7 'B' */
5759 3, 3, /* string 8 'AAR' */
5760 1, 1, /* string 9 'C' */
5761 1, 1, /* string a 'D' */
5762 3, 1, /* string b 'one' */
5763 3, 1, /* string c 'two' */
5764 0, 0, /* string d '' */
5765 4, 1, /* string e 'four' */
5766 4, 1, /* string f 'five' */
5767 };
5768
5769 static void test_stringtable(void)
5770 {
5771 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5772 IStorage *stg = NULL;
5773 IStream *stm;
5774 WCHAR name[0x20];
5775 HRESULT hr;
5776 const char *query;
5777 char buffer[MAX_PATH];
5778 WCHAR data[MAX_PATH];
5779 DWORD sz, read;
5780 UINT r;
5781
5782 static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5783 static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5784 static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5785 static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5786 static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5787
5788 DeleteFileA(msifile);
5789
5790 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5791 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5792
5793 query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5794 r = run_query(hdb, 0, query);
5795 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5796
5797 query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5798 r = run_query(hdb, 0, query);
5799 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5800
5801 /* insert persistent row */
5802 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5803 r = run_query(hdb, 0, query);
5804 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5805
5806 /* insert persistent row */
5807 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5808 r = run_query(hdb, 0, query);
5809 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5810
5811 /* open a view */
5812 query = "SELECT * FROM `MOO`";
5813 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5814 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5815 r = MsiViewExecute(hview, 0);
5816 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5817
5818 hrec = MsiCreateRecord(2);
5819
5820 r = MsiRecordSetInteger(hrec, 1, 3);
5821 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5822 r = MsiRecordSetStringA(hrec, 2, "three");
5823 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5824
5825 /* insert a nonpersistent row */
5826 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5827 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5828
5829 r = MsiCloseHandle(hrec);
5830 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5831 r = MsiViewClose(hview);
5832 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5833 r = MsiCloseHandle(hview);
5834 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5835
5836 /* insert persistent row */
5837 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5838 r = run_query(hdb, 0, query);
5839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5840
5841 /* insert persistent row */
5842 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5843 r = run_query(hdb, 0, query);
5844 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5845
5846 r = MsiDatabaseCommit(hdb);
5847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5848
5849 r = MsiCloseHandle(hdb);
5850 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5851
5852 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
5853 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5854
5855 query = "SELECT * FROM `MOO`";
5856 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5857 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5858
5859 r = MsiViewExecute(hview, 0);
5860 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5861
5862 r = MsiViewFetch(hview, &hrec);
5863 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5864
5865 r = MsiRecordGetFieldCount(hrec);
5866 ok(r == 2, "Expected 2, got %d\n", r);
5867
5868 r = MsiRecordGetInteger(hrec, 1);
5869 ok(r == 1, "Expected 1, got %d\n", r);
5870
5871 sz = sizeof(buffer);
5872 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5873 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5874 ok(!lstrcmpA(buffer, "one"), "Expected one, got '%s'\n", buffer);
5875
5876 r = MsiCloseHandle(hrec);
5877 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5878
5879 r = MsiViewFetch(hview, &hrec);
5880 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5881
5882 r = MsiViewClose(hview);
5883 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5884 r = MsiCloseHandle(hview);
5885 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5886 r = MsiCloseHandle(hrec);
5887 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5888
5889 query = "SELECT * FROM `AAR`";
5890 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5891 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5892
5893 r = MsiViewExecute(hview, 0);
5894 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5895
5896 r = MsiViewFetch(hview, &hrec);
5897 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5898
5899 r = MsiRecordGetFieldCount(hrec);
5900 ok(r == 2, "Expected 2, got %d\n", r);
5901
5902 r = MsiRecordGetInteger(hrec, 1);
5903 ok(r == 2, "Expected 2, got %d\n", r);
5904
5905 sz = sizeof(buffer);
5906 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5907 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5908 ok(!lstrcmpA(buffer, "two"), "Expected two, got '%s'\n", buffer);
5909
5910 r = MsiCloseHandle(hrec);
5911 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5912
5913 r = MsiViewFetch(hview, &hrec);
5914 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5915
5916 r = MsiRecordGetFieldCount(hrec);
5917 ok(r == 2, "Expected 2, got %d\n", r);
5918
5919 r = MsiRecordGetInteger(hrec, 1);
5920 ok(r == 5, "Expected 5, got %d\n", r);
5921
5922 sz = sizeof(buffer);
5923 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
5924 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5925 ok(!lstrcmpA(buffer, "five"), "Expected five, got '%s'\n", buffer);
5926
5927 r = MsiCloseHandle(hrec);
5928 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5929
5930 r = MsiViewFetch(hview, &hrec);
5931 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5932
5933 r = MsiViewClose(hview);
5934 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5935 r = MsiCloseHandle(hview);
5936 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5937 r = MsiCloseHandle(hrec);
5938 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5939 r = MsiCloseHandle(hdb);
5940 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5941
5942 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5943 hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5944 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5945 ok(stg != NULL, "Expected non-NULL storage\n");
5946
5947 hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5948 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5949 ok(stm != NULL, "Expected non-NULL stream\n");
5950
5951 hr = IStream_Read(stm, data, MAX_PATH, &read);
5952 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5953 ok(read == 4, "Expected 4, got %d\n", read);
5954 todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5955
5956 hr = IStream_Release(stm);
5957 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5958
5959 hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5960 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5961 ok(stm != NULL, "Expected non-NULL stream\n");
5962
5963 hr = IStream_Read(stm, data, MAX_PATH, &read);
5964 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5965 ok(read == 8, "Expected 8, got %d\n", read);
5966 todo_wine
5967 {
5968 ok(!memcmp(data, data11, read), "Unexpected data\n");
5969 }
5970
5971 hr = IStream_Release(stm);
5972 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5973
5974 hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5975 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5976 ok(stm != NULL, "Expected non-NULL stream\n");
5977
5978 hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5979 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5980 ok(read == 24, "Expected 24, got %d\n", read);
5981 ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5982
5983 hr = IStream_Release(stm);
5984 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5985
5986 hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5987 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5988 ok(stm != NULL, "Expected non-NULL stream\n");
5989
5990 hr = IStream_Read(stm, data, MAX_PATH, &read);
5991 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5992 todo_wine
5993 {
5994 ok(read == 64, "Expected 64, got %d\n", read);
5995 ok(!memcmp(data, data13, read), "Unexpected data\n");
5996 }
5997
5998 hr = IStream_Release(stm);
5999 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6000
6001 hr = IStorage_Release(stg);
6002 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
6003
6004 DeleteFileA(msifile);
6005 }
6006
6007 static void test_viewmodify_delete(void)
6008 {
6009 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
6010 UINT r;
6011 const char *query;
6012 char buffer[0x100];
6013 DWORD sz;
6014
6015 DeleteFileA(msifile);
6016
6017 /* just MsiOpenDatabase should not create a file */
6018 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6019 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6020
6021 query = "CREATE TABLE `phone` ( "
6022 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
6023 "PRIMARY KEY `id`)";
6024 r = run_query(hdb, 0, query);
6025 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6026
6027 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6028 "VALUES('1', 'Alan', '5030581')";
6029 r = run_query(hdb, 0, query);
6030 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6031
6032 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6033 "VALUES('2', 'Barry', '928440')";
6034 r = run_query(hdb, 0, query);
6035 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6036
6037 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
6038 "VALUES('3', 'Cindy', '2937550')";
6039 r = run_query(hdb, 0, query);
6040 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6041
6042 query = "SELECT * FROM `phone` WHERE `id` <= 2";
6043 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6044 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6045 r = MsiViewExecute(hview, 0);
6046 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6047 r = MsiViewFetch(hview, &hrec);
6048 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6049
6050 /* delete 1 */
6051 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6052 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6053
6054 r = MsiCloseHandle(hrec);
6055 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6056 r = MsiViewFetch(hview, &hrec);
6057 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6058
6059 /* delete 2 */
6060 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6061 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6062
6063 r = MsiCloseHandle(hrec);
6064 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6065 r = MsiViewClose(hview);
6066 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6067 r = MsiCloseHandle(hview);
6068 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6069
6070 query = "SELECT * FROM `phone`";
6071 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6072 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6073 r = MsiViewExecute(hview, 0);
6074 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6075 r = MsiViewFetch(hview, &hrec);
6076 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6077
6078 r = MsiRecordGetInteger(hrec, 1);
6079 ok(r == 3, "Expected 3, got %d\n", r);
6080
6081 sz = sizeof(buffer);
6082 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
6083 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6084 ok(!lstrcmpA(buffer, "Cindy"), "Expected Cindy, got %s\n", buffer);
6085
6086 sz = sizeof(buffer);
6087 r = MsiRecordGetStringA(hrec, 3, buffer, &sz);
6088 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6089 ok(!lstrcmpA(buffer, "2937550"), "Expected 2937550, got %s\n", buffer);
6090
6091 r = MsiCloseHandle(hrec);
6092 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6093
6094 r = MsiViewFetch(hview, &hrec);
6095 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6096
6097 r = MsiViewClose(hview);
6098 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6099 r = MsiCloseHandle(hview);
6100 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6101 r = MsiCloseHandle(hdb);
6102 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6103 }
6104
6105 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
6106 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
6107 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
6108
6109 static const WCHAR data14[] = { /* _StringPool */
6110 /* len, refs */
6111 0, 0, /* string 0 '' */
6112 };
6113
6114 static const struct {
6115 LPCWSTR name;
6116 const void *data;
6117 DWORD size;
6118 } database_table_data[] =
6119 {
6120 {_Tables, NULL, 0},
6121 {_StringData, NULL, 0},
6122 {_StringPool, data14, sizeof data14},
6123 };
6124
6125 static void enum_stream_names(IStorage *stg)
6126 {
6127 IEnumSTATSTG *stgenum = NULL;
6128 IStream *stm;
6129 HRESULT hr;
6130 STATSTG stat;
6131 ULONG n, count;
6132 BYTE data[MAX_PATH];
6133 BYTE check[MAX_PATH];
6134 DWORD sz;
6135
6136 memset(check, 'a', MAX_PATH);
6137
6138 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
6139 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6140
6141 n = 0;
6142 while(TRUE)
6143 {
6144 count = 0;
6145 hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
6146 if(FAILED(hr) || !count)
6147 break;
6148
6149 ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
6150 "Expected table %d name to match\n", n);
6151
6152 stm = NULL;
6153 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
6154 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
6155 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6156 ok(stm != NULL, "Expected non-NULL stream\n");
6157
6158 CoTaskMemFree(stat.pwcsName);
6159
6160 sz = MAX_PATH;
6161 memset(data, 'a', MAX_PATH);
6162 hr = IStream_Read(stm, data, sz, &count);
6163 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6164
6165 ok(count == database_table_data[n].size,
6166 "Expected %d, got %d\n", database_table_data[n].size, count);
6167
6168 if (!database_table_data[n].size)
6169 ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
6170 else
6171 ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
6172 "Expected table %d data to match\n", n);
6173
6174 IStream_Release(stm);
6175 n++;
6176 }
6177
6178 ok(n == 3, "Expected 3, got %d\n", n);
6179
6180 IEnumSTATSTG_Release(stgenum);
6181 }
6182
6183 static void test_defaultdatabase(void)
6184 {
6185 UINT r;
6186 HRESULT hr;
6187 MSIHANDLE hdb;
6188 IStorage *stg = NULL;
6189
6190 DeleteFileA(msifile);
6191
6192 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6193 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6194
6195 r = MsiDatabaseCommit(hdb);
6196 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6197
6198 MsiCloseHandle(hdb);
6199
6200 hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
6201 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
6202 ok(stg != NULL, "Expected non-NULL stg\n");
6203
6204 enum_stream_names(stg);
6205
6206 IStorage_Release(stg);
6207 DeleteFileA(msifile);
6208 }
6209
6210 static void test_order(void)
6211 {
6212 MSIHANDLE hdb, hview, hrec;
6213 CHAR buffer[MAX_PATH];
6214 LPCSTR query;
6215 UINT r, sz;
6216 int val;
6217
6218 hdb = create_db();
6219 ok(hdb, "failed to create db\n");
6220
6221 query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
6222 r = run_query(hdb, 0, query);
6223 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6224
6225 query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
6226 r = run_query(hdb, 0, query);
6227 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6228
6229 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
6230 r = run_query(hdb, 0, query);
6231 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6232
6233 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
6234 r = run_query(hdb, 0, query);
6235 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6236
6237 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
6238 r = run_query(hdb, 0, query);
6239 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6240
6241 query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
6242 r = run_query(hdb, 0, query);
6243 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6244
6245 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
6246 r = run_query(hdb, 0, query);
6247 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6248
6249 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
6250 r = run_query(hdb, 0, query);
6251 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6252
6253 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
6254 r = run_query(hdb, 0, query);
6255 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6256
6257 query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
6258 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6259 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6260 r = MsiViewExecute(hview, 0);
6261 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6262
6263 r = MsiViewFetch(hview, &hrec);
6264 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6265
6266 val = MsiRecordGetInteger(hrec, 1);
6267 ok(val == 3, "Expected 3, got %d\n", val);
6268
6269 val = MsiRecordGetInteger(hrec, 2);
6270 ok(val == 4, "Expected 3, got %d\n", val);
6271
6272 MsiCloseHandle(hrec);
6273
6274 r = MsiViewFetch(hview, &hrec);
6275 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6276
6277 val = MsiRecordGetInteger(hrec, 1);
6278 ok(val == 5, "Expected 5, got %d\n", val);
6279
6280 val = MsiRecordGetInteger(hrec, 2);
6281 ok(val == 6, "Expected 6, got %d\n", val);
6282
6283 MsiCloseHandle(hrec);
6284
6285 r = MsiViewFetch(hview, &hrec);
6286 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6287
6288 val = MsiRecordGetInteger(hrec, 1);
6289 ok(val == 1, "Expected 1, got %d\n", val);
6290
6291 val = MsiRecordGetInteger(hrec, 2);
6292 ok(val == 2, "Expected 2, got %d\n", val);
6293
6294 MsiCloseHandle(hrec);
6295
6296 r = MsiViewFetch(hview, &hrec);
6297 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6298
6299 MsiViewClose(hview);
6300 MsiCloseHandle(hview);
6301
6302 query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6303 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6304 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6305 r = MsiViewExecute(hview, 0);
6306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6307
6308 r = MsiViewFetch(hview, &hrec);
6309 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6310
6311 val = MsiRecordGetInteger(hrec, 1);
6312 ok(val == 1, "Expected 1, got %d\n", val);
6313
6314 val = MsiRecordGetInteger(hrec, 2);
6315 ok(val == 12, "Expected 12, got %d\n", val);
6316
6317 MsiCloseHandle(hrec);
6318
6319 r = MsiViewFetch(hview, &hrec);
6320 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6321
6322 val = MsiRecordGetInteger(hrec, 1);
6323 ok(val == 3, "Expected 3, got %d\n", val);
6324
6325 val = MsiRecordGetInteger(hrec, 2);
6326 ok(val == 12, "Expected 12, got %d\n", val);
6327
6328 MsiCloseHandle(hrec);
6329
6330 r = MsiViewFetch(hview, &hrec);
6331 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6332
6333 val = MsiRecordGetInteger(hrec, 1);
6334 ok(val == 5, "Expected 5, got %d\n", val);
6335
6336 val = MsiRecordGetInteger(hrec, 2);
6337 ok(val == 12, "Expected 12, got %d\n", val);
6338
6339 MsiCloseHandle(hrec);
6340
6341 r = MsiViewFetch(hview, &hrec);
6342 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6343
6344 val = MsiRecordGetInteger(hrec, 1);
6345 ok(val == 1, "Expected 1, got %d\n", val);
6346
6347 val = MsiRecordGetInteger(hrec, 2);
6348 ok(val == 14, "Expected 14, got %d\n", val);
6349
6350 MsiCloseHandle(hrec);
6351
6352 r = MsiViewFetch(hview, &hrec);
6353 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6354
6355 val = MsiRecordGetInteger(hrec, 1);
6356 ok(val == 3, "Expected 3, got %d\n", val);
6357
6358 val = MsiRecordGetInteger(hrec, 2);
6359 ok(val == 14, "Expected 14, got %d\n", val);
6360
6361 MsiCloseHandle(hrec);
6362
6363 r = MsiViewFetch(hview, &hrec);
6364 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6365
6366 val = MsiRecordGetInteger(hrec, 1);
6367 ok(val == 5, "Expected 5, got %d\n", val);
6368
6369 val = MsiRecordGetInteger(hrec, 2);
6370 ok(val == 14, "Expected 14, got %d\n", val);
6371
6372 MsiCloseHandle(hrec);
6373
6374 r = MsiViewFetch(hview, &hrec);
6375 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6376
6377 val = MsiRecordGetInteger(hrec, 1);
6378 ok(val == 1, "Expected 1, got %d\n", val);
6379
6380 val = MsiRecordGetInteger(hrec, 2);
6381 ok(val == 10, "Expected 10, got %d\n", val);
6382
6383 MsiCloseHandle(hrec);
6384
6385 r = MsiViewFetch(hview, &hrec);
6386 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6387
6388 val = MsiRecordGetInteger(hrec, 1);
6389 ok(val == 3, "Expected 3, got %d\n", val);
6390
6391 val = MsiRecordGetInteger(hrec, 2);
6392 ok(val == 10, "Expected 10, got %d\n", val);
6393
6394 MsiCloseHandle(hrec);
6395
6396 r = MsiViewFetch(hview, &hrec);
6397 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6398
6399 val = MsiRecordGetInteger(hrec, 1);
6400 ok(val == 5, "Expected 5, got %d\n", val);
6401
6402 val = MsiRecordGetInteger(hrec, 2);
6403 ok(val == 10, "Expected 10, got %d\n", val);
6404
6405 MsiCloseHandle(hrec);
6406
6407 r = MsiViewFetch(hview, &hrec);
6408 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6409
6410 MsiViewClose(hview);
6411 MsiCloseHandle(hview);
6412
6413 query = "SELECT * FROM `Empty` ORDER BY `A`";
6414 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6415 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6416 r = MsiViewExecute(hview, 0);
6417 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6418
6419 r = MsiViewFetch(hview, &hrec);
6420 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6421
6422 MsiViewClose(hview);
6423 MsiCloseHandle(hview);
6424
6425 query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6426 r = run_query(hdb, 0, query);
6427 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6428
6429 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno', 2)";
6430 r = run_query(hdb, 0, query);
6431 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6432
6433 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos', 3)";
6434 r = run_query(hdb, 0, query);
6435 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6436
6437 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres', 1)";
6438 r = run_query(hdb, 0, query);
6439 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6440
6441 query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6442 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6443 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6444 r = MsiViewExecute(hview, 0);
6445 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6446
6447 r = MsiViewFetch(hview, &hrec);
6448 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6449
6450 sz = sizeof(buffer);
6451 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
6452 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6453 ok(!lstrcmpA(buffer, "dos"), "Expected \"dos\", got \"%s\"\n", buffer);
6454
6455 r = MsiRecordGetInteger(hrec, 2);
6456 ok(r == 3, "Expected 3, got %d\n", r);
6457
6458 MsiCloseHandle(hrec);
6459
6460 r = MsiViewFetch(hview, &hrec);
6461 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6462
6463 MsiViewClose(hview);
6464 MsiCloseHandle(hview);
6465 MsiCloseHandle(hdb);
6466 }
6467
6468 static void test_viewmodify_delete_temporary(void)
6469 {
6470 MSIHANDLE hdb, hview, hrec;
6471 const char *query;
6472 UINT r;
6473
6474 DeleteFileA(msifile);
6475
6476 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6477 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6478
6479 query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6480 r = run_query(hdb, 0, query);
6481 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6482
6483 query = "SELECT * FROM `Table`";
6484 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6485 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6486 r = MsiViewExecute(hview, 0);
6487 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6488
6489 hrec = MsiCreateRecord(1);
6490 MsiRecordSetInteger(hrec, 1, 1);
6491
6492 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6493 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6494
6495 MsiCloseHandle(hrec);
6496
6497 hrec = MsiCreateRecord(1);
6498 MsiRecordSetInteger(hrec, 1, 2);
6499
6500 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6501 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6502
6503 MsiCloseHandle(hrec);
6504
6505 hrec = MsiCreateRecord(1);
6506 MsiRecordSetInteger(hrec, 1, 3);
6507
6508 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6509 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6510
6511 MsiCloseHandle(hrec);
6512
6513 hrec = MsiCreateRecord(1);
6514 MsiRecordSetInteger(hrec, 1, 4);
6515
6516 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6517 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6518
6519 MsiCloseHandle(hrec);
6520 MsiViewClose(hview);
6521 MsiCloseHandle(hview);
6522
6523 query = "SELECT * FROM `Table` WHERE `A` = 2";
6524 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6525 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6526 r = MsiViewExecute(hview, 0);
6527 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6528 r = MsiViewFetch(hview, &hrec);
6529 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6530
6531 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6532 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6533
6534 MsiCloseHandle(hrec);
6535 MsiViewClose(hview);
6536 MsiCloseHandle(hview);
6537
6538 query = "SELECT * FROM `Table` WHERE `A` = 3";
6539 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6540 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6541 r = MsiViewExecute(hview, 0);
6542 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6543 r = MsiViewFetch(hview, &hrec);
6544 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6545
6546 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6547 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6548
6549 MsiCloseHandle(hrec);
6550 MsiViewClose(hview);
6551 MsiCloseHandle(hview);
6552
6553 query = "SELECT * FROM `Table` ORDER BY `A`";
6554 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6555 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6556 r = MsiViewExecute(hview, 0);
6557 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6558
6559 r = MsiViewFetch(hview, &hrec);
6560 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6561
6562 r = MsiRecordGetInteger(hrec, 1);
6563 ok(r == 1, "Expected 1, got %d\n", r);
6564
6565 MsiCloseHandle(hrec);
6566
6567 r = MsiViewFetch(hview, &hrec);
6568 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6569
6570 r = MsiRecordGetInteger(hrec, 1);
6571 ok(r == 4, "Expected 4, got %d\n", r);
6572
6573 MsiCloseHandle(hrec);
6574
6575 r = MsiViewFetch(hview, &hrec);
6576 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6577
6578 MsiViewClose(hview);
6579 MsiCloseHandle(hview);
6580 MsiCloseHandle(hdb);
6581 DeleteFileA(msifile);
6582 }
6583
6584 static void test_deleterow(void)
6585 {
6586 MSIHANDLE hdb, hview, hrec;
6587 const char *query;
6588 char buf[MAX_PATH];
6589 UINT r;
6590 DWORD size;
6591
6592 DeleteFileA(msifile);
6593
6594 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6595 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6596
6597 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6598 r = run_query(hdb, 0, query);
6599 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6600
6601 query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6602 r = run_query(hdb, 0, query);
6603 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6604
6605 query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6606 r = run_query(hdb, 0, query);
6607 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6608
6609 query = "DELETE FROM `Table` WHERE `A` = 'one'";
6610 r = run_query(hdb, 0, query);
6611 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6612
6613 r = MsiDatabaseCommit(hdb);
6614 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6615
6616 MsiCloseHandle(hdb);
6617
6618 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
6619 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6620
6621 query = "SELECT * FROM `Table`";
6622 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6623 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6624 r = MsiViewExecute(hview, 0);
6625 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6626
6627 r = MsiViewFetch(hview, &hrec);
6628 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6629
6630 size = MAX_PATH;
6631 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6632 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6633 ok(!lstrcmpA(buf, "two"), "Expected two, got %s\n", buf);
6634
6635 MsiCloseHandle(hrec);
6636
6637 r = MsiViewFetch(hview, &hrec);
6638 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6639
6640 MsiViewClose(hview);
6641 MsiCloseHandle(hview);
6642 MsiCloseHandle(hdb);
6643 DeleteFileA(msifile);
6644 }
6645
6646 static const CHAR import_dat[] = "A\n"
6647 "s72\n"
6648 "Table\tA\n"
6649 "This is a new 'string' ok\n";
6650
6651 static void test_quotes(void)
6652 {
6653 MSIHANDLE hdb, hview, hrec;
6654 const char *query;
6655 char buf[MAX_PATH];
6656 UINT r;
6657 DWORD size;
6658
6659 DeleteFileA(msifile);
6660
6661 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6662 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6663
6664 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6665 r = run_query(hdb, 0, query);
6666 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6667
6668 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6669 r = run_query(hdb, 0, query);
6670 ok(r == ERROR_BAD_QUERY_SYNTAX,
6671 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6672
6673 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6674 r = run_query(hdb, 0, query);
6675 ok(r == ERROR_BAD_QUERY_SYNTAX,
6676 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6677
6678 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6679 r = run_query(hdb, 0, query);
6680 ok(r == ERROR_BAD_QUERY_SYNTAX,
6681 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6682
6683 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6684 r = run_query(hdb, 0, query);
6685 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6686
6687 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6688 r = run_query(hdb, 0, query);
6689 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6690
6691 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6692 r = run_query(hdb, 0, query);
6693 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6694
6695 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6696 r = run_query(hdb, 0, query);
6697 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6698
6699 query = "SELECT * FROM `Table`";
6700 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6701 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6702
6703 r = MsiViewExecute(hview, 0);
6704 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6705
6706 r = MsiViewFetch(hview, &hrec);
6707 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6708
6709 size = MAX_PATH;
6710 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6711 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6712 ok(!lstrcmpA(buf, "This is a \"string\" ok"),
6713 "Expected \"This is a \"string\" ok\", got %s\n", buf);
6714
6715 MsiCloseHandle(hrec);
6716
6717 r = MsiViewFetch(hview, &hrec);
6718 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6719
6720 MsiViewClose(hview);
6721 MsiCloseHandle(hview);
6722
6723 write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6724
6725 r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6726 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6727
6728 DeleteFileA("import.idt");
6729
6730 query = "SELECT * FROM `Table`";
6731 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6732 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6733
6734 r = MsiViewExecute(hview, 0);
6735 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6736
6737 r = MsiViewFetch(hview, &hrec);
6738 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6739
6740 size = MAX_PATH;
6741 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6742 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6743 ok(!lstrcmpA(buf, "This is a new 'string' ok"),
6744 "Expected \"This is a new 'string' ok\", got %s\n", buf);
6745
6746 MsiCloseHandle(hrec);
6747
6748 r = MsiViewFetch(hview, &hrec);
6749 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6750
6751 MsiViewClose(hview);
6752 MsiCloseHandle(hview);
6753 MsiCloseHandle(hdb);
6754 DeleteFileA(msifile);
6755 }
6756
6757 static void test_carriagereturn(void)
6758 {
6759 MSIHANDLE hdb, hview, hrec;
6760 const char *query;
6761 char buf[MAX_PATH];
6762 UINT r;
6763 DWORD size;
6764
6765 DeleteFileA(msifile);
6766
6767 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6768 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6769
6770 query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6771 r = run_query(hdb, 0, query);
6772 ok(r == ERROR_BAD_QUERY_SYNTAX,
6773 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6774
6775 query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6776 r = run_query(hdb, 0, query);
6777 ok(r == ERROR_BAD_QUERY_SYNTAX,
6778 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6779
6780 query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6781 r = run_query(hdb, 0, query);
6782 ok(r == ERROR_BAD_QUERY_SYNTAX,
6783 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6784
6785 query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6786 r = run_query(hdb, 0, query);
6787 ok(r == ERROR_BAD_QUERY_SYNTAX,
6788 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6789
6790 query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6791 r = run_query(hdb, 0, query);
6792 ok(r == ERROR_BAD_QUERY_SYNTAX,
6793 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6794
6795 query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6796 r = run_query(hdb, 0, query);
6797 ok(r == ERROR_BAD_QUERY_SYNTAX,
6798 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6799
6800 query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6801 r = run_query(hdb, 0, query);
6802 ok(r == ERROR_BAD_QUERY_SYNTAX,
6803 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6804
6805 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6806 r = run_query(hdb, 0, query);
6807 ok(r == ERROR_BAD_QUERY_SYNTAX,
6808 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6809
6810 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6811 r = run_query(hdb, 0, query);
6812 ok(r == ERROR_BAD_QUERY_SYNTAX,
6813 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6814
6815 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6816 r = run_query(hdb, 0, query);
6817 ok(r == ERROR_BAD_QUERY_SYNTAX,
6818 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6819
6820 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6821 r = run_query(hdb, 0, query);
6822 ok(r == ERROR_BAD_QUERY_SYNTAX,
6823 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6824
6825 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6826 r = run_query(hdb, 0, query);
6827 ok(r == ERROR_BAD_QUERY_SYNTAX,
6828 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6829
6830 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6831 r = run_query(hdb, 0, query);
6832 ok(r == ERROR_BAD_QUERY_SYNTAX,
6833 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6834
6835 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6836 r = run_query(hdb, 0, query);
6837 ok(r == ERROR_BAD_QUERY_SYNTAX,
6838 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6839
6840 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6841 r = run_query(hdb, 0, query);
6842 ok(r == ERROR_BAD_QUERY_SYNTAX,
6843 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6844
6845 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6846 r = run_query(hdb, 0, query);
6847 ok(r == ERROR_BAD_QUERY_SYNTAX,
6848 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6849
6850 query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6851 r = run_query(hdb, 0, query);
6852 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6853
6854 query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6855 r = run_query(hdb, 0, query);
6856 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6857
6858 query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6859 r = run_query(hdb, 0, query);
6860 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6861
6862 query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6863 r = run_query(hdb, 0, query);
6864 ok(r == ERROR_BAD_QUERY_SYNTAX,
6865 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6866
6867 query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6868 r = run_query(hdb, 0, query);
6869 ok(r == ERROR_BAD_QUERY_SYNTAX,
6870 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6871
6872 query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6873 r = run_query(hdb, 0, query);
6874 ok(r == ERROR_BAD_QUERY_SYNTAX,
6875 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6876
6877 query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6878 r = run_query(hdb, 0, query);
6879 ok(r == ERROR_BAD_QUERY_SYNTAX,
6880 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6881
6882 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6883 r = run_query(hdb, 0, query);
6884 ok(r == ERROR_BAD_QUERY_SYNTAX,
6885 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6886
6887 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6888 r = run_query(hdb, 0, query);
6889 ok(r == ERROR_BAD_QUERY_SYNTAX,
6890 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6891
6892 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6893 r = run_query(hdb, 0, query);
6894 ok(r == ERROR_BAD_QUERY_SYNTAX,
6895 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6896
6897 query = "SELECT * FROM `_Tables`";
6898 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6899 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6900 r = MsiViewExecute(hview, 0);
6901 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6902
6903 r = MsiViewFetch(hview, &hrec);
6904 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6905
6906 size = MAX_PATH;
6907 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6908 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909 ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf);
6910
6911 MsiCloseHandle(hrec);
6912
6913 r = MsiViewFetch(hview, &hrec);
6914 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6915
6916 size = MAX_PATH;
6917 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6918 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6919 ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf);
6920
6921 MsiCloseHandle(hrec);
6922
6923 r = MsiViewFetch(hview, &hrec);
6924 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6925
6926 size = MAX_PATH;
6927 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6928 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6929 ok(!lstrcmpA(buf, "Three\r"), "Expected \"Three\r\", got \"%s\"\n", buf);
6930
6931 MsiCloseHandle(hrec);
6932
6933 r = MsiViewFetch(hview, &hrec);
6934 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6935
6936 MsiViewClose(hview);
6937 MsiCloseHandle(hview);
6938
6939 MsiCloseHandle(hdb);
6940 DeleteFileA(msifile);
6941 }
6942
6943 static void test_noquotes(void)
6944 {
6945 MSIHANDLE hdb, hview, hrec;
6946 const char *query;
6947 char buf[MAX_PATH];
6948 UINT r;
6949 DWORD size;
6950
6951 DeleteFileA(msifile);
6952
6953 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6954 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6955
6956 query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6957 r = run_query(hdb, 0, query);
6958 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6959
6960 query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6961 r = run_query(hdb, 0, query);
6962 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6963
6964 query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6965 r = run_query(hdb, 0, query);
6966 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6967
6968 query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6969 r = run_query(hdb, 0, query);
6970 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6971
6972 query = "SELECT * FROM `_Tables`";
6973 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6974 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6975 r = MsiViewExecute(hview, 0);
6976 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6977
6978 r = MsiViewFetch(hview, &hrec);
6979 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6980
6981 size = MAX_PATH;
6982 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6983 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6984 ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
6985
6986 MsiCloseHandle(hrec);
6987
6988 r = MsiViewFetch(hview, &hrec);
6989 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6990
6991 size = MAX_PATH;
6992 r = MsiRecordGetStringA(hrec, 1, buf, &size);
6993 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6994 ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
6995
6996 MsiCloseHandle(hrec);
6997
6998 r = MsiViewFetch(hview, &hrec);
6999 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7000
7001 size = MAX_PATH;
7002 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7003 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7004 ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7005
7006 MsiCloseHandle(hrec);
7007
7008 r = MsiViewFetch(hview, &hrec);
7009 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7010
7011 MsiViewClose(hview);
7012 MsiCloseHandle(hview);
7013
7014 query = "SELECT * FROM `_Columns`";
7015 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7016 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7017 r = MsiViewExecute(hview, 0);
7018 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7019
7020 r = MsiViewFetch(hview, &hrec);
7021 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7022
7023 size = MAX_PATH;
7024 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7025 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7026 ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
7027
7028 r = MsiRecordGetInteger(hrec, 2);
7029 ok(r == 1, "Expected 1, got %d\n", r);
7030
7031 size = MAX_PATH;
7032 r = MsiRecordGetStringA(hrec, 3, buf, &size);
7033 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7034 ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7035
7036 MsiCloseHandle(hrec);
7037
7038 r = MsiViewFetch(hview, &hrec);
7039 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7040
7041 size = MAX_PATH;
7042 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7043 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7044 ok(!lstrcmpA(buf, "Table2"), "Expected \"Table2\", got \"%s\"\n", buf);
7045
7046 r = MsiRecordGetInteger(hrec, 2);
7047 ok(r == 1, "Expected 1, got %d\n", r);
7048
7049 size = MAX_PATH;
7050 r = MsiRecordGetStringA(hrec, 3, buf, &size);
7051 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7052 ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7053
7054 MsiCloseHandle(hrec);
7055
7056 r = MsiViewFetch(hview, &hrec);
7057 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7058
7059 size = MAX_PATH;
7060 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7061 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7062 ok(!lstrcmpA(buf, "Table3"), "Expected \"Table3\", got \"%s\"\n", buf);
7063
7064 r = MsiRecordGetInteger(hrec, 2);
7065 ok(r == 1, "Expected 1, got %d\n", r);
7066
7067 size = MAX_PATH;
7068 r = MsiRecordGetStringA(hrec, 3, buf, &size);
7069 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7070 ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7071
7072 MsiCloseHandle(hrec);
7073
7074 r = MsiViewFetch(hview, &hrec);
7075 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7076
7077 MsiViewClose(hview);
7078 MsiCloseHandle(hview);
7079
7080 query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
7081 r = run_query(hdb, 0, query);
7082 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7083
7084 query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
7085 r = run_query(hdb, 0, query);
7086 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7087
7088 query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
7089 r = run_query(hdb, 0, query);
7090 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7091
7092 query = "SELECT * FROM Table WHERE `A` = 'hi'";
7093 r = run_query(hdb, 0, query);
7094 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7095
7096 query = "SELECT * FROM `Table` WHERE `A` = hi";
7097 r = run_query(hdb, 0, query);
7098 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7099
7100 query = "SELECT * FROM Table";
7101 r = run_query(hdb, 0, query);
7102 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7103
7104 query = "SELECT * FROM Table2";
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_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7112
7113 MsiViewClose(hview);
7114 MsiCloseHandle(hview);
7115
7116 query = "SELECT * FROM `Table` WHERE A = 'hi'";
7117 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7118 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7119 r = MsiViewExecute(hview, 0);
7120 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7121
7122 r = MsiViewFetch(hview, &hrec);
7123 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7124
7125 size = MAX_PATH;
7126 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7127 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7128 ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
7129
7130 MsiCloseHandle(hrec);
7131
7132 r = MsiViewFetch(hview, &hrec);
7133 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7134
7135 MsiViewClose(hview);
7136 MsiCloseHandle(hview);
7137 MsiCloseHandle(hdb);
7138 DeleteFileA(msifile);
7139 }
7140
7141 static void read_file_data(LPCSTR filename, LPSTR buffer)
7142 {
7143 HANDLE file;
7144 DWORD read;
7145
7146 file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
7147 ZeroMemory(buffer, MAX_PATH);
7148 ReadFile(file, buffer, MAX_PATH, &read, NULL);
7149 CloseHandle(file);
7150 }
7151
7152 static void test_forcecodepage(void)
7153 {
7154 MSIHANDLE hdb;
7155 const char *query;
7156 char buffer[MAX_PATH];
7157 UINT r;
7158
7159 DeleteFileA(msifile);
7160 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
7161
7162 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7163 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7164
7165 query = "SELECT * FROM `_ForceCodepage`";
7166 r = run_query(hdb, 0, query);
7167 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7168
7169 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
7170 r = run_query(hdb, 0, query);
7171 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172
7173 query = "SELECT * FROM `_ForceCodepage`";
7174 r = run_query(hdb, 0, query);
7175 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7176
7177 r = MsiDatabaseCommit(hdb);
7178 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7179
7180 query = "SELECT * FROM `_ForceCodepage`";
7181 r = run_query(hdb, 0, query);
7182 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7183
7184 MsiCloseHandle(hdb);
7185
7186 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7187 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7188
7189 query = "SELECT * FROM `_ForceCodepage`";
7190 r = run_query(hdb, 0, query);
7191 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7192
7193 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7194 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7195
7196 read_file_data("forcecodepage.idt", buffer);
7197 ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
7198 "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7199
7200 create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7201
7202 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7203 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7204
7205 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
7206 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7207
7208 read_file_data("forcecodepage.idt", buffer);
7209 ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
7210 "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
7211
7212 create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
7213
7214 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
7215 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_SUCCESS, got %d\n", r);
7216
7217 MsiCloseHandle(hdb);
7218 DeleteFileA(msifile);
7219 DeleteFileA("forcecodepage.idt");
7220 }
7221
7222 static void test_viewmodify_refresh(void)
7223 {
7224 MSIHANDLE hdb, hview, hrec;
7225 const char *query;
7226 char buffer[MAX_PATH];
7227 UINT r;
7228 DWORD size;
7229
7230 DeleteFileA(msifile);
7231
7232 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7233 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7234
7235 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
7236 r = run_query(hdb, 0, query);
7237 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7238
7239 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7240 r = run_query(hdb, 0, query);
7241 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7242
7243 query = "SELECT * FROM `Table`";
7244 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7245 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7246 r = MsiViewExecute(hview, 0);
7247 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7248
7249 r = MsiViewFetch(hview, &hrec);
7250 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7251
7252 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
7253 r = run_query(hdb, 0, query);
7254 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7255
7256 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7257 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7258
7259 size = MAX_PATH;
7260 r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7261 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7262 ok(!lstrcmpA(buffer, "hi"), "Expected \"hi\", got \"%s\"\n", buffer);
7263 ok(size == 2, "Expected 2, got %d\n", size);
7264
7265 r = MsiRecordGetInteger(hrec, 2);
7266 ok(r == 2, "Expected 2, got %d\n", r);
7267
7268 MsiCloseHandle(hrec);
7269 MsiViewClose(hview);
7270 MsiCloseHandle(hview);
7271
7272 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
7273 r = run_query(hdb, 0, query);
7274 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7275
7276 query = "SELECT * FROM `Table` WHERE `B` = 3";
7277 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7278 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7279 r = MsiViewExecute(hview, 0);
7280 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7281
7282 r = MsiViewFetch(hview, &hrec);
7283 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7284
7285 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
7286 r = run_query(hdb, 0, query);
7287 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7288
7289 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
7290 r = run_query(hdb, 0, query);
7291 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7292
7293 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7294 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7295
7296 size = MAX_PATH;
7297 r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7298 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7299 ok(!lstrcmpA(buffer, "hello"), "Expected \"hello\", got \"%s\"\n", buffer);
7300 ok(size == 5, "Expected 5, got %d\n", size);
7301
7302 r = MsiRecordGetInteger(hrec, 2);
7303 ok(r == 2, "Expected 2, got %d\n", r);
7304
7305 MsiCloseHandle(hrec);
7306 MsiViewClose(hview);
7307 MsiCloseHandle(hview);
7308 MsiCloseHandle(hdb);
7309 DeleteFileA(msifile);
7310 }
7311
7312 static void test_where_viewmodify(void)
7313 {
7314 MSIHANDLE hdb, hview, hrec;
7315 const char *query;
7316 UINT r;
7317
7318 DeleteFileA(msifile);
7319
7320 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7322
7323 query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7324 r = run_query(hdb, 0, query);
7325 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7326
7327 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
7328 r = run_query(hdb, 0, query);
7329 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7330
7331 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
7332 r = run_query(hdb, 0, query);
7333 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7334
7335 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
7336 r = run_query(hdb, 0, query);
7337 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7338
7339 /* `B` = 3 doesn't match, but the view shouldn't be executed */
7340 query = "SELECT * FROM `Table` WHERE `B` = 3";
7341 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7342 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7343
7344 hrec = MsiCreateRecord(2);
7345 MsiRecordSetInteger(hrec, 1, 7);
7346 MsiRecordSetInteger(hrec, 2, 8);
7347
7348 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
7349 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7350
7351 MsiCloseHandle(hrec);
7352 MsiViewClose(hview);
7353 MsiCloseHandle(hview);
7354
7355 query = "SELECT * FROM `Table` WHERE `A` = 7";
7356 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7357 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7358 r = MsiViewExecute(hview, 0);
7359 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7360
7361 r = MsiViewFetch(hview, &hrec);
7362 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7363
7364 r = MsiRecordGetInteger(hrec, 1);
7365 ok(r == 7, "Expected 7, got %d\n", r);
7366
7367 r = MsiRecordGetInteger(hrec, 2);
7368 ok(r == 8, "Expected 8, got %d\n", r);
7369
7370 MsiRecordSetInteger(hrec, 2, 9);
7371
7372 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7373 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7374
7375 MsiCloseHandle(hrec);
7376 MsiViewClose(hview);
7377 MsiCloseHandle(hview);
7378
7379 query = "SELECT * FROM `Table` WHERE `A` = 7";
7380 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7381 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7382 r = MsiViewExecute(hview, 0);
7383 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7384
7385 r = MsiViewFetch(hview, &hrec);
7386 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7387
7388 r = MsiRecordGetInteger(hrec, 1);
7389 ok(r == 7, "Expected 7, got %d\n", r);
7390
7391 r = MsiRecordGetInteger(hrec, 2);
7392 ok(r == 9, "Expected 9, got %d\n", r);
7393
7394 query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7395 r = run_query(hdb, 0, query);
7396 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7397
7398 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7399 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7400
7401 r = MsiRecordGetInteger(hrec, 1);
7402 ok(r == 7, "Expected 7, got %d\n", r);
7403
7404 r = MsiRecordGetInteger(hrec, 2);
7405 ok(r == 10, "Expected 10, got %d\n", r);
7406
7407 MsiCloseHandle(hrec);
7408 MsiViewClose(hview);
7409 MsiCloseHandle(hview);
7410 MsiCloseHandle(hdb);
7411 }
7412
7413 static BOOL create_storage(LPCSTR name)
7414 {
7415 WCHAR nameW[MAX_PATH];
7416 IStorage *stg;
7417 IStream *stm;
7418 HRESULT hr;
7419 DWORD count;
7420 BOOL res = FALSE;
7421
7422 MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7423 hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7424 STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7425 if (FAILED(hr))
7426 return FALSE;
7427
7428 hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7429 0, 0, &stm);
7430 if (FAILED(hr))
7431 goto done;
7432
7433 hr = IStream_Write(stm, "stgdata", 8, &count);
7434 if (SUCCEEDED(hr))
7435 res = TRUE;
7436
7437 done:
7438 IStream_Release(stm);
7439 IStorage_Release(stg);
7440
7441 return res;
7442 }
7443
7444 static void test_storages_table(void)
7445 {
7446 MSIHANDLE hdb, hview, hrec;
7447 IStorage *stg, *inner;
7448 IStream *stm;
7449 char file[MAX_PATH];
7450 char buf[MAX_PATH];
7451 WCHAR name[MAX_PATH];
7452 LPCSTR query;
7453 HRESULT hr;
7454 DWORD size;
7455 UINT r;
7456
7457 hdb = create_db();
7458 ok(hdb, "failed to create db\n");
7459
7460 r = MsiDatabaseCommit(hdb);
7461 ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7462
7463 MsiCloseHandle(hdb);
7464
7465 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb);
7466 ok(r == ERROR_SUCCESS , "Failed to open database\n");
7467
7468 /* check the column types */
7469 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7470 ok(hrec, "failed to get column info hrecord\n");
7471 ok(check_record(hrec, 1, "s62"), "wrong hrecord type\n");
7472 ok(check_record(hrec, 2, "V0"), "wrong hrecord type\n");
7473
7474 MsiCloseHandle(hrec);
7475
7476 /* now try the names */
7477 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7478 ok(hrec, "failed to get column info hrecord\n");
7479 ok(check_record(hrec, 1, "Name"), "wrong hrecord type\n");
7480 ok(check_record(hrec, 2, "Data"), "wrong hrecord type\n");
7481
7482 MsiCloseHandle(hrec);
7483
7484 create_storage("storage.bin");
7485
7486 hrec = MsiCreateRecord(2);
7487 MsiRecordSetStringA(hrec, 1, "stgname");
7488
7489 r = MsiRecordSetStreamA(hrec, 2, "storage.bin");
7490 ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7491
7492 DeleteFileA("storage.bin");
7493
7494 query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7495 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7496 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7497
7498 r = MsiViewExecute(hview, hrec);
7499 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7500
7501 MsiCloseHandle(hrec);
7502 MsiViewClose(hview);
7503 MsiCloseHandle(hview);
7504
7505 query = "SELECT `Name`, `Data` FROM `_Storages`";
7506 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7507 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7508
7509 r = MsiViewExecute(hview, 0);
7510 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7511
7512 r = MsiViewFetch(hview, &hrec);
7513 ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7514
7515 size = MAX_PATH;
7516 r = MsiRecordGetStringA(hrec, 1, file, &size);
7517 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7518 ok(!lstrcmpA(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7519
7520 size = MAX_PATH;
7521 lstrcpyA(buf, "apple");
7522 r = MsiRecordReadStream(hrec, 2, buf, &size);
7523 ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7524 ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7525 ok(size == 0, "Expected 0, got %d\n", size);
7526
7527 MsiCloseHandle(hrec);
7528
7529 r = MsiViewFetch(hview, &hrec);
7530 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7531
7532 MsiViewClose(hview);
7533 MsiCloseHandle(hview);
7534
7535 MsiDatabaseCommit(hdb);
7536 MsiCloseHandle(hdb);
7537
7538 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7539 hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7540 STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7541 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7542 ok(stg != NULL, "Expected non-NULL storage\n");
7543
7544 MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7545 hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7546 NULL, 0, &inner);
7547 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7548 ok(inner != NULL, "Expected non-NULL storage\n");
7549
7550 MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7551 hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7552 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
7553 ok(stm != NULL, "Expected non-NULL stream\n");
7554
7555 hr = IStream_Read(stm, buf, MAX_PATH, &size);
7556 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
7557 ok(size == 8, "Expected 8, got %d\n", size);
7558 ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7559
7560 IStream_Release(stm);
7561 IStorage_Release(inner);
7562
7563 IStorage_Release(stg);
7564 DeleteFileA(msifile);
7565 }
7566
7567 static void test_dbtopackage(void)
7568 {
7569 MSIHANDLE hdb, hpkg;
7570 CHAR package[12], buf[MAX_PATH];
7571 DWORD size;
7572 UINT r;
7573
7574 /* create an empty database, transact mode */
7575 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7576 ok(r == ERROR_SUCCESS, "Failed to create database\n");
7577
7578 set_summary_info(hdb);
7579
7580 r = create_directory_table(hdb);
7581 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7582
7583 r = create_custom_action_table(hdb);
7584 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7585
7586 r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7587 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7588
7589 sprintf(package, "#%u", hdb);
7590 r = MsiOpenPackageA(package, &hpkg);
7591 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7592 {
7593 skip("Not enough rights to perform tests\n");
7594 goto error;
7595 }
7596 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7597
7598 /* property is not set yet */
7599 size = MAX_PATH;
7600 lstrcpyA(buf, "kiwi");
7601 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7602 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7603 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7604 ok(size == 0, "Expected 0, got %d\n", size);
7605
7606 /* run the custom action to set the property */
7607 r = MsiDoActionA(hpkg, "SetProp");
7608 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7609
7610 /* property is now set */
7611 size = MAX_PATH;
7612 lstrcpyA(buf, "kiwi");
7613 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7614 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7615 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7616 ok(size == 5, "Expected 5, got %d\n", size);
7617
7618 MsiCloseHandle(hpkg);
7619
7620 /* reset the package */
7621 r = MsiOpenPackageA(package, &hpkg);
7622 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7623
7624 /* property is not set anymore */
7625 size = MAX_PATH;
7626 lstrcpyA(buf, "kiwi");
7627 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7628 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7629 todo_wine
7630 {
7631 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7632 ok(size == 0, "Expected 0, got %d\n", size);
7633 }
7634
7635 MsiCloseHandle(hdb);
7636 MsiCloseHandle(hpkg);
7637
7638 /* create an empty database, direct mode */
7639 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7640 ok(r == ERROR_SUCCESS, "Failed to create database\n");
7641
7642 set_summary_info(hdb);
7643
7644 r = create_directory_table(hdb);
7645 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7646
7647 r = create_custom_action_table(hdb);
7648 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7649
7650 r = add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7651 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7652
7653 sprintf(package, "#%u", hdb);
7654 r = MsiOpenPackageA(package, &hpkg);
7655 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7656
7657 /* property is not set yet */
7658 size = MAX_PATH;
7659 lstrcpyA(buf, "kiwi");
7660 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7661 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7662 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7663 ok(size == 0, "Expected 0, got %d\n", size);
7664
7665 /* run the custom action to set the property */
7666 r = MsiDoActionA(hpkg, "SetProp");
7667 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7668
7669 /* property is now set */
7670 size = MAX_PATH;
7671 lstrcpyA(buf, "kiwi");
7672 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7673 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7674 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7675 ok(size == 5, "Expected 5, got %d\n", size);
7676
7677 MsiCloseHandle(hpkg);
7678
7679 /* reset the package */
7680 r = MsiOpenPackageA(package, &hpkg);
7681 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7682
7683 /* property is not set anymore */
7684 size = MAX_PATH;
7685 lstrcpyA(buf, "kiwi");
7686 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7688 todo_wine
7689 {
7690 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7691 ok(size == 0, "Expected 0, got %d\n", size);
7692 }
7693
7694 MsiCloseHandle(hpkg);
7695
7696 error:
7697 MsiCloseHandle(hdb);
7698 DeleteFileA(msifile);
7699 }
7700
7701 static void test_droptable(void)
7702 {
7703 MSIHANDLE hdb, hview, hrec;
7704 CHAR buf[MAX_PATH];
7705 LPCSTR query;
7706 DWORD size;
7707 UINT r;
7708
7709 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7710 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7711
7712 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7713 r = run_query(hdb, 0, query);
7714 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7715
7716 query = "SELECT * FROM `One`";
7717 r = do_query(hdb, query, &hrec);
7718 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7719
7720 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7721 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7722 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7723 r = MsiViewExecute(hview, 0);
7724 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7725
7726 r = MsiViewFetch(hview, &hrec);
7727 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7728
7729 size = MAX_PATH;
7730 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7731 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7732 ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7733
7734 MsiCloseHandle(hrec);
7735 MsiViewClose(hview);
7736 MsiCloseHandle(hview);
7737
7738 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7739 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7740 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7741 r = MsiViewExecute(hview, 0);
7742 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7743
7744 r = MsiViewFetch(hview, &hrec);
7745 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7746
7747 size = MAX_PATH;
7748 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7749 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7750 ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7751
7752 r = MsiRecordGetInteger(hrec, 2);
7753 ok(r == 1, "Expected 1, got %d\n", r);
7754
7755 size = MAX_PATH;
7756 r = MsiRecordGetStringA(hrec, 3, buf, &size);
7757 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7758 ok(!lstrcmpA(buf, "A"), "Expected \"A\", got \"%s\"\n", buf);
7759
7760 MsiCloseHandle(hrec);
7761
7762 r = MsiViewFetch(hview, &hrec);
7763 ok(r == ERROR_NO_MORE_ITEMS,
7764 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7765
7766 MsiViewClose(hview);
7767 MsiCloseHandle(hview);
7768
7769 query = "DROP `One`";
7770 r = run_query(hdb, 0, query);
7771 ok(r == ERROR_BAD_QUERY_SYNTAX,
7772 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7773
7774 query = "DROP TABLE";
7775 r = run_query(hdb, 0, query);
7776 ok(r == ERROR_BAD_QUERY_SYNTAX,
7777 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7778
7779 query = "DROP TABLE `One`";
7780 hview = 0;
7781 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7782 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7783 r = MsiViewExecute(hview, 0);
7784 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7785
7786 r = MsiViewFetch(hview, &hrec);
7787 ok(r == ERROR_FUNCTION_FAILED,
7788 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7789
7790 MsiViewClose(hview);
7791 MsiCloseHandle(hview);
7792
7793 query = "SELECT * FROM `IDontExist`";
7794 r = do_query(hdb, query, &hrec);
7795 ok(r == ERROR_BAD_QUERY_SYNTAX,
7796 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7797
7798 query = "SELECT * FROM `One`";
7799 r = do_query(hdb, query, &hrec);
7800 ok(r == ERROR_BAD_QUERY_SYNTAX,
7801 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7802
7803 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7804 r = run_query(hdb, 0, query);
7805 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7806
7807 query = "DROP TABLE One";
7808 r = run_query(hdb, 0, query);
7809 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7810
7811 query = "SELECT * FROM `One`";
7812 r = do_query(hdb, query, &hrec);
7813 ok(r == ERROR_BAD_QUERY_SYNTAX,
7814 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7815
7816 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7817 r = do_query(hdb, query, &hrec);
7818 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7819
7820 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7821 r = do_query(hdb, query, &hrec);
7822 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7823
7824 query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7825 r = run_query(hdb, 0, query);
7826 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7827
7828 query = "SELECT * FROM `One`";
7829 r = do_query(hdb, query, &hrec);
7830 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7831
7832 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7833 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7834 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7835 r = MsiViewExecute(hview, 0);
7836 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7837
7838 r = MsiViewFetch(hview, &hrec);
7839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7840
7841 size = MAX_PATH;
7842 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7844 ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7845
7846 MsiCloseHandle(hrec);
7847 MsiViewClose(hview);
7848 MsiCloseHandle(hview);
7849
7850 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7851 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7852 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7853 r = MsiViewExecute(hview, 0);
7854 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7855
7856 r = MsiViewFetch(hview, &hrec);
7857 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7858
7859 size = MAX_PATH;
7860 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7861 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7862 ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7863
7864 r = MsiRecordGetInteger(hrec, 2);
7865 ok(r == 1, "Expected 1, got %d\n", r);
7866
7867 size = MAX_PATH;
7868 r = MsiRecordGetStringA(hrec, 3, buf, &size);
7869 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7870 ok(!lstrcmpA(buf, "B"), "Expected \"B\", got \"%s\"\n", buf);
7871
7872 MsiCloseHandle(hrec);
7873
7874 r = MsiViewFetch(hview, &hrec);
7875 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7876
7877 size = MAX_PATH;
7878 r = MsiRecordGetStringA(hrec, 1, buf, &size);
7879 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7880 ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
7881
7882 r = MsiRecordGetInteger(hrec, 2);
7883 ok(r == 2, "Expected 2, got %d\n", r);
7884
7885 size = MAX_PATH;
7886 r = MsiRecordGetStringA(hrec, 3, buf, &size);
7887 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7888 ok(!lstrcmpA(buf, "C"), "Expected \"C\", got \"%s\"\n", buf);
7889
7890 MsiCloseHandle(hrec);
7891
7892 r = MsiViewFetch(hview, &hrec);
7893 ok(r == ERROR_NO_MORE_ITEMS,
7894 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7895
7896 MsiViewClose(hview);
7897 MsiCloseHandle(hview);
7898
7899 query = "DROP TABLE One";
7900 r = run_query(hdb, 0, query);
7901 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7902
7903 query = "SELECT * FROM `One`";
7904 r = do_query(hdb, query, &hrec);
7905 ok(r == ERROR_BAD_QUERY_SYNTAX,
7906 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7907
7908 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7909 r = do_query(hdb, query, &hrec);
7910 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7911
7912 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7913 r = do_query(hdb, query, &hrec);
7914 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7915
7916 MsiCloseHandle(hdb);
7917 DeleteFileA(msifile);
7918 }
7919
7920 static void test_dbmerge(void)
7921 {
7922 static const WCHAR refdbW[] = {'r','e','f','d','b','.','m','s','i',0};
7923 MSIHANDLE hdb, href, hview, hrec;
7924 CHAR buf[MAX_PATH];
7925 LPCSTR query;
7926 DWORD size;
7927 UINT r;
7928
7929 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7930 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7931
7932 r = MsiOpenDatabaseW(refdbW, MSIDBOPEN_CREATE, &href);
7933 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7934
7935 /* hDatabase is invalid */
7936 r = MsiDatabaseMergeA(0, href, "MergeErrors");
7937 ok(r == ERROR_INVALID_HANDLE,
7938 "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7939
7940 /* hDatabaseMerge is invalid */
7941 r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7942 ok(r == ERROR_INVALID_HANDLE,
7943 "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7944
7945 /* szTableName is NULL */
7946 r = MsiDatabaseMergeA(hdb, href, NULL);
7947 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7948
7949 /* szTableName is empty */
7950 r = MsiDatabaseMergeA(hdb, href, "");
7951 ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7952
7953 /* both DBs empty, szTableName is valid */
7954 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7955 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7956
7957 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7958 r = run_query(hdb, 0, query);
7959 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7960
7961 query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7962 r = run_query(href, 0, query);
7963 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7964
7965 /* column types don't match */
7966 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7967 ok(r == ERROR_DATATYPE_MISMATCH,
7968 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7969
7970 /* nothing in MergeErrors */
7971 query = "SELECT * FROM `MergeErrors`";
7972 r = do_query(hdb, query, &hrec);
7973 ok(r == ERROR_BAD_QUERY_SYNTAX,
7974 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7975
7976 query = "DROP TABLE `One`";
7977 r = run_query(hdb, 0, query);
7978 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7979
7980 query = "DROP TABLE `One`";
7981 r = run_query(href, 0, query);
7982 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7983
7984 query = "CREATE TABLE `One` ( "
7985 "`A` CHAR(72), "
7986 "`B` CHAR(56), "
7987 "`C` CHAR(64) LOCALIZABLE, "
7988 "`D` LONGCHAR, "
7989 "`E` CHAR(72) NOT NULL, "
7990 "`F` CHAR(56) NOT NULL, "
7991 "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7992 "`H` LONGCHAR NOT NULL "
7993 "PRIMARY KEY `A` )";
7994 r = run_query(hdb, 0, query);
7995 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7996
7997 query = "CREATE TABLE `One` ( "
7998 "`A` CHAR(64), "
7999 "`B` CHAR(64), "
8000 "`C` CHAR(64), "
8001 "`D` CHAR(64), "
8002 "`E` CHAR(64) NOT NULL, "
8003 "`F` CHAR(64) NOT NULL, "
8004 "`G` CHAR(64) NOT NULL, "
8005 "`H` CHAR(64) NOT NULL "
8006 "PRIMARY KEY `A` )";
8007 r = run_query(href, 0, query);
8008 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8009
8010 /* column sting types don't match exactly */
8011 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8012 ok(r == ERROR_SUCCESS,
8013 "Expected ERROR_SUCCESS, got %d\n", r);
8014
8015 /* nothing in MergeErrors */
8016 query = "SELECT * FROM `MergeErrors`";
8017 r = do_query(hdb, query, &hrec);
8018 ok(r == ERROR_BAD_QUERY_SYNTAX,
8019 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8020
8021 query = "DROP TABLE `One`";
8022 r = run_query(hdb, 0, query);
8023 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8024
8025 query = "DROP TABLE `One`";
8026 r = run_query(href, 0, query);
8027 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8028
8029 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8030 r = run_query(hdb, 0, query);
8031 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8032
8033 query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
8034 r = run_query(href, 0, query);
8035 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8036
8037 /* column names don't match */
8038 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8039 ok(r == ERROR_DATATYPE_MISMATCH,
8040 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8041
8042 /* nothing in MergeErrors */
8043 query = "SELECT * FROM `MergeErrors`";
8044 r = do_query(hdb, query, &hrec);
8045 ok(r == ERROR_BAD_QUERY_SYNTAX,
8046 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8047
8048 query = "DROP TABLE `One`";
8049 r = run_query(hdb, 0, query);
8050 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8051
8052 query = "DROP TABLE `One`";
8053 r = run_query(href, 0, query);
8054 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8055
8056 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8057 r = run_query(hdb, 0, query);
8058 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8059
8060 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
8061 r = run_query(href, 0, query);
8062 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8063
8064 /* primary keys don't match */
8065 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8066 ok(r == ERROR_DATATYPE_MISMATCH,
8067 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8068
8069 /* nothing in MergeErrors */
8070 query = "SELECT * FROM `MergeErrors`";
8071 r = do_query(hdb, query, &hrec);
8072 ok(r == ERROR_BAD_QUERY_SYNTAX,
8073 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8074
8075 query = "DROP TABLE `One`";
8076 r = run_query(hdb, 0, query);
8077 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8078
8079 query = "DROP TABLE `One`";
8080 r = run_query(href, 0, query);
8081 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8082
8083 query = "CREATE TABLE `One` ( `A` INT, `B` INT 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` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
8088 r = run_query(href, 0, query);
8089 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8090
8091 /* number of primary keys doesn't match */
8092 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8093 ok(r == ERROR_DATATYPE_MISMATCH,
8094 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
8095
8096 /* nothing in MergeErrors */
8097 query = "SELECT * FROM `MergeErrors`";
8098 r = do_query(hdb, query, &hrec);
8099 ok(r == ERROR_BAD_QUERY_SYNTAX,
8100 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8101
8102 query = "DROP TABLE `One`";
8103 r = run_query(hdb, 0, query);
8104 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8105
8106 query = "DROP TABLE `One`";
8107 r = run_query(href, 0, query);
8108 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8109
8110 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8111 r = run_query(hdb, 0, query);
8112 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8113
8114 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8115 r = run_query(href, 0, query);
8116 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8117
8118 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8119 r = run_query(href, 0, query);
8120 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8121
8122 /* number of columns doesn't match */
8123 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8124 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8125
8126 query = "SELECT * FROM `One`";
8127 r = do_query(hdb, query, &hrec);
8128 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8129
8130 r = MsiRecordGetInteger(hrec, 1);
8131 ok(r == 1, "Expected 1, got %d\n", r);
8132
8133 r = MsiRecordGetInteger(hrec, 2);
8134 ok(r == 2, "Expected 2, got %d\n", r);
8135
8136 r = MsiRecordGetInteger(hrec, 3);
8137 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8138
8139 MsiCloseHandle(hrec);
8140
8141 /* nothing in MergeErrors */
8142 query = "SELECT * FROM `MergeErrors`";
8143 r = do_query(hdb, query, &hrec);
8144 ok(r == ERROR_BAD_QUERY_SYNTAX,
8145 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8146
8147 query = "DROP TABLE `One`";
8148 r = run_query(hdb, 0, query);
8149 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8150
8151 query = "DROP TABLE `One`";
8152 r = run_query(href, 0, query);
8153 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8154
8155 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8156 r = run_query(hdb, 0, query);
8157 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8158
8159 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
8160 r = run_query(href, 0, query);
8161 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8162
8163 query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8164 r = run_query(href, 0, query);
8165 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8166
8167 /* number of columns doesn't match */
8168 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8169 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8170
8171 query = "SELECT * FROM `One`";
8172 r = do_query(hdb, query, &hrec);
8173 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8174
8175 r = MsiRecordGetInteger(hrec, 1);
8176 ok(r == 1, "Expected 1, got %d\n", r);
8177
8178 r = MsiRecordGetInteger(hrec, 2);
8179 ok(r == 2, "Expected 2, got %d\n", r);
8180
8181 r = MsiRecordGetInteger(hrec, 3);
8182 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
8183
8184 MsiCloseHandle(hrec);
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 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 = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
8205 r = run_query(hdb, 0, query);
8206 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8207
8208 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
8209 r = run_query(hdb, 0, query);
8210 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8211
8212 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
8213 r = run_query(href, 0, query);
8214 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8215
8216 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
8217 r = run_query(href, 0, query);
8218 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8219
8220 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
8221 r = run_query(href, 0, query);
8222 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8223
8224 /* primary keys match, rows do not */
8225 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8226 ok(r == ERROR_FUNCTION_FAILED,
8227 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8228
8229 /* nothing in MergeErrors */
8230 query = "SELECT * FROM `MergeErrors`";
8231 r = do_query(hdb, query, &hrec);
8232 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8233
8234 size = MAX_PATH;
8235 r = MsiRecordGetStringA(hrec, 1, buf, &size);
8236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8237 ok(!lstrcmpA(buf, "One"), "Expected \"One\", got \"%s\"\n", buf);
8238
8239 r = MsiRecordGetInteger(hrec, 2);
8240 ok(r == 2, "Expected 2, got %d\n", r);
8241
8242 MsiCloseHandle(hrec);
8243
8244 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
8245 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8246
8247 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
8248 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8249
8250 size = MAX_PATH;
8251 r = MsiRecordGetStringA(hrec, 1, buf, &size);
8252 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8253 ok(!lstrcmpA(buf, "Table"), "Expected \"Table\", got \"%s\"\n", buf);
8254
8255 size = MAX_PATH;
8256 r = MsiRecordGetStringA(hrec, 2, buf, &size);
8257 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8258 ok(!lstrcmpA(buf, "NumRowMergeConflicts"),
8259 "Expected \"NumRowMergeConflicts\", got \"%s\"\n", buf);
8260
8261 MsiCloseHandle(hrec);
8262
8263 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
8264 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8265
8266 size = MAX_PATH;
8267 r = MsiRecordGetStringA(hrec, 1, buf, &size);
8268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8269 ok(!lstrcmpA(buf, "s255"), "Expected \"s255\", got \"%s\"\n", buf);
8270
8271 size = MAX_PATH;
8272 r = MsiRecordGetStringA(hrec, 2, buf, &size);
8273 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8274 ok(!lstrcmpA(buf, "i2"), "Expected \"i2\", got \"%s\"\n", buf);
8275
8276 MsiCloseHandle(hrec);
8277 MsiViewClose(hview);
8278 MsiCloseHandle(hview);
8279
8280 query = "DROP TABLE `MergeErrors`";
8281 r = run_query(hdb, 0, query);
8282 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8283
8284 query = "DROP TABLE `One`";
8285 r = run_query(hdb, 0, query);
8286 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8287
8288 query = "DROP TABLE `One`";
8289 r = run_query(href, 0, query);
8290 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8291
8292 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8293 r = run_query(href, 0, query);
8294 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8295
8296 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8297 r = run_query(href, 0, query);
8298 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8299
8300 /* table from merged database is not in target database */
8301 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8302 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8303
8304 query = "SELECT * FROM `One`";
8305 r = do_query(hdb, query, &hrec);
8306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8307
8308 r = MsiRecordGetInteger(hrec, 1);
8309 ok(r == 1, "Expected 1, got %d\n", r);
8310
8311 size = MAX_PATH;
8312 r = MsiRecordGetStringA(hrec, 2, buf, &size);
8313 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8314 ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8315
8316 MsiCloseHandle(hrec);
8317
8318 /* nothing in MergeErrors */
8319 query = "SELECT * FROM `MergeErrors`";
8320 r = do_query(hdb, query, &hrec);
8321 ok(r == ERROR_BAD_QUERY_SYNTAX,
8322 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8323
8324 query = "DROP TABLE `One`";
8325 r = run_query(hdb, 0, query);
8326 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8327
8328 query = "DROP TABLE `One`";
8329 r = run_query(href, 0, query);
8330 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8331
8332 query = "CREATE TABLE `One` ( "
8333 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8334 r = run_query(hdb, 0, query);
8335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8336
8337 query = "CREATE TABLE `One` ( "
8338 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
8339 r = run_query(href, 0, query);
8340 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8341
8342 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
8343 r = run_query(href, 0, query);
8344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8345
8346 /* primary key is string */
8347 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8348 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8349
8350 query = "SELECT * FROM `One`";
8351 r = do_query(hdb, query, &hrec);
8352 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8353
8354 size = MAX_PATH;
8355 r = MsiRecordGetStringA(hrec, 1, buf, &size);
8356 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8357 ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8358
8359 r = MsiRecordGetInteger(hrec, 2);
8360 ok(r == 1, "Expected 1, got %d\n", r);
8361
8362 MsiCloseHandle(hrec);
8363
8364 /* nothing in MergeErrors */
8365 query = "SELECT * FROM `MergeErrors`";
8366 r = do_query(hdb, query, &hrec);
8367 ok(r == ERROR_BAD_QUERY_SYNTAX,
8368 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8369
8370 create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
8371
8372 GetCurrentDirectoryA(MAX_PATH, buf);
8373 r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
8374 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8375
8376 query = "DROP TABLE `One`";
8377 r = run_query(hdb, 0, query);
8378 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8379
8380 query = "DROP TABLE `One`";
8381 r = run_query(href, 0, query);
8382 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8383
8384 query = "CREATE TABLE `One` ( "
8385 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8386 r = run_query(hdb, 0, query);
8387 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8388
8389 query = "CREATE TABLE `One` ( "
8390 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
8391 r = run_query(href, 0, query);
8392 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8393
8394 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
8395 r = run_query(href, 0, query);
8396 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8397
8398 /* code page does not match */
8399 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8400 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8401
8402 query = "SELECT * FROM `One`";
8403 r = do_query(hdb, query, &hrec);
8404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8405
8406 r = MsiRecordGetInteger(hrec, 1);
8407 ok(r == 1, "Expected 1, got %d\n", r);
8408
8409 size = MAX_PATH;
8410 r = MsiRecordGetStringA(hrec, 2, buf, &size);
8411 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8412 ok(!lstrcmpA(buf, "hi"), "Expected \"hi\", got \"%s\"\n", buf);
8413
8414 MsiCloseHandle(hrec);
8415
8416 /* nothing in MergeErrors */
8417 query = "SELECT * FROM `MergeErrors`";
8418 r = do_query(hdb, query, &hrec);
8419 ok(r == ERROR_BAD_QUERY_SYNTAX,
8420 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8421
8422 query = "DROP TABLE `One`";
8423 r = run_query(hdb, 0, query);
8424 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8425
8426 query = "DROP TABLE `One`";
8427 r = run_query(href, 0, query);
8428 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8429
8430 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8431 r = run_query(hdb, 0, query);
8432 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8433
8434 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
8435 r = run_query(href, 0, query);
8436 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8437
8438 create_file("binary.dat");
8439 hrec = MsiCreateRecord(1);
8440 MsiRecordSetStreamA(hrec, 1, "binary.dat");
8441
8442 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
8443 r = run_query(href, hrec, query);
8444 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8445
8446 MsiCloseHandle(hrec);
8447
8448 /* binary data to merge */
8449 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8450 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8451
8452 query = "SELECT * FROM `One`";
8453 r = do_query(hdb, query, &hrec);
8454 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8455
8456 r = MsiRecordGetInteger(hrec, 1);
8457 ok(r == 1, "Expected 1, got %d\n", r);
8458
8459 size = MAX_PATH;
8460 ZeroMemory(buf, MAX_PATH);
8461 r = MsiRecordReadStream(hrec, 2, buf, &size);
8462 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8463 ok(!lstrcmpA(buf, "binary.dat\n"),
8464 "Expected \"binary.dat\\n\", got \"%s\"\n", buf);
8465
8466 MsiCloseHandle(hrec);
8467
8468 /* nothing in MergeErrors */
8469 query = "SELECT * FROM `MergeErrors`";
8470 r = do_query(hdb, query, &hrec);
8471 ok(r == ERROR_BAD_QUERY_SYNTAX,
8472 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8473
8474 query = "DROP TABLE `One`";
8475 r = run_query(hdb, 0, query);
8476 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8477
8478 query = "DROP TABLE `One`";
8479 r = run_query(href, 0, query);
8480 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8481
8482 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
8483 r = run_query(hdb, 0, query);
8484 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8485 r = run_query(href, 0, query);
8486 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8487
8488 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8489 r = run_query(href, 0, query);
8490 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8491
8492 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8493 r = run_query(href, 0, query);
8494 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8495
8496 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8497 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8498
8499 query = "SELECT * FROM `One`";
8500 r = MsiDatabaseOpenViewA(hdb, query, &hview);
8501 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8502 r = MsiViewExecute(hview, 0);
8503 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8504
8505 r = MsiViewFetch(hview, &hrec);
8506 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8507
8508 r = MsiRecordGetInteger(hrec, 1);
8509 ok(r == 1, "Expected 1, got %d\n", r);
8510
8511 size = MAX_PATH;
8512 r = MsiRecordGetStringA(hrec, 2, buf, &size);
8513 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8514 ok(!lstrcmpA(buf, "foo"), "Expected \"foo\", got \"%s\"\n", buf);
8515
8516 MsiCloseHandle(hrec);
8517
8518 r = MsiViewFetch(hview, &hrec);
8519 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8520
8521 r = MsiRecordGetInteger(hrec, 1);
8522 ok(r == 2, "Expected 2, got %d\n", r);
8523
8524 size = MAX_PATH;
8525 r = MsiRecordGetStringA(hrec, 2, buf, &size);
8526 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8527 ok(!lstrcmpA(buf, "bar"), "Expected \"bar\", got \"%s\"\n", buf);
8528
8529 MsiCloseHandle(hrec);
8530
8531 r = MsiViewFetch(hview, &hrec);
8532 ok(r == ERROR_NO_MORE_ITEMS,
8533 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8534
8535 MsiViewClose(hview);
8536 MsiCloseHandle(hview);
8537
8538 MsiCloseHandle(hdb);
8539 MsiCloseHandle(href);
8540 DeleteFileA(msifile);
8541 DeleteFileW(refdbW);
8542 DeleteFileA("codepage.idt");
8543 DeleteFileA("binary.dat");
8544 }
8545
8546 static void test_select_with_tablenames(void)
8547 {
8548 MSIHANDLE hdb, view, rec;
8549 LPCSTR query;
8550 UINT r;
8551 int i;
8552
8553 int vals[4][2] = {
8554 {1,12},
8555 {4,12},
8556 {1,15},
8557 {4,15}};
8558
8559 hdb = create_db();
8560 ok(hdb, "failed to create db\n");
8561
8562 /* Build a pair of tables with the same column names, but unique data */
8563 query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8564 r = run_query(hdb, 0, query);
8565 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8566
8567 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8568 r = run_query(hdb, 0, query);
8569 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8570
8571 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8572 r = run_query(hdb, 0, query);
8573 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8574
8575 query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8576 r = run_query(hdb, 0, query);
8577 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8578
8579 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8580 r = run_query(hdb, 0, query);
8581 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8582
8583 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8584 r = run_query(hdb, 0, query);
8585 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8586
8587
8588 /* Test that selection based on prefixing the column with the table
8589 * actually selects the right data */
8590
8591 query = "SELECT T1.A, T2.B FROM T1,T2";
8592 r = MsiDatabaseOpenViewA(hdb, query, &view);
8593 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8594 r = MsiViewExecute(view, 0);
8595 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8596
8597 for (i = 0; i < 4; i++)
8598 {
8599 r = MsiViewFetch(view, &rec);
8600 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8601
8602 r = MsiRecordGetInteger(rec, 1);
8603 ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8604
8605 r = MsiRecordGetInteger(rec, 2);
8606 ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8607
8608 MsiCloseHandle(rec);
8609 }
8610
8611 r = MsiViewFetch(view, &rec);
8612 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8613
8614 MsiViewClose(view);
8615 MsiCloseHandle(view);
8616 MsiCloseHandle(hdb);
8617 DeleteFileA(msifile);
8618 }
8619
8620 static const UINT ordervals[6][3] =
8621 {
8622 { MSI_NULL_INTEGER, 12, 13 },
8623 { 1, 2, 3 },
8624 { 6, 4, 5 },
8625 { 8, 9, 7 },
8626 { 10, 11, MSI_NULL_INTEGER },
8627 { 14, MSI_NULL_INTEGER, 15 }
8628 };
8629
8630 static void test_insertorder(void)
8631 {
8632 MSIHANDLE hdb, view, rec;
8633 LPCSTR query;
8634 UINT r;
8635 int i;
8636
8637 hdb = create_db();
8638 ok(hdb, "failed to create db\n");
8639
8640 query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8641 r = run_query(hdb, 0, query);
8642 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8643
8644 query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8645 r = run_query(hdb, 0, query);
8646 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8647
8648 query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8649 r = run_query(hdb, 0, query);
8650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8651
8652 query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8653 r = run_query(hdb, 0, query);
8654 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8655
8656 query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8657 r = run_query(hdb, 0, query);
8658 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8659
8660 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8661 r = run_query(hdb, 0, query);
8662 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8663
8664 /* fails because the primary key already
8665 * has an MSI_NULL_INTEGER value set above
8666 */
8667 query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8668 r = run_query(hdb, 0, query);
8669 ok(r == ERROR_FUNCTION_FAILED,
8670 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8671
8672 /* replicate the error where primary key is set twice */
8673 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8674 r = run_query(hdb, 0, query);
8675 ok(r == ERROR_FUNCTION_FAILED,
8676 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8677
8678 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8679 r = run_query(hdb, 0, query);
8680 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8681
8682 query = "INSERT INTO `T` VALUES ( 16 )";
8683 r = run_query(hdb, 0, query);
8684 ok(r == ERROR_BAD_QUERY_SYNTAX,
8685 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8686
8687 query = "INSERT INTO `T` VALUES ( 17, 18 )";
8688 r = run_query(hdb, 0, query);
8689 ok(r == ERROR_BAD_QUERY_SYNTAX,
8690 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8691
8692 query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8693 r = run_query(hdb, 0, query);
8694 ok(r == ERROR_BAD_QUERY_SYNTAX,
8695 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8696
8697 query = "SELECT * FROM `T`";
8698 r = MsiDatabaseOpenViewA(hdb, query, &view);
8699 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8700 r = MsiViewExecute(view, 0);
8701 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8702
8703 for (i = 0; i < 6; i++)
8704 {
8705 r = MsiViewFetch(view, &rec);
8706 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8707
8708 r = MsiRecordGetInteger(rec, 1);
8709 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8710
8711 r = MsiRecordGetInteger(rec, 2);
8712 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8713
8714 r = MsiRecordGetInteger(rec, 3);
8715 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8716
8717 MsiCloseHandle(rec);
8718 }
8719
8720 r = MsiViewFetch(view, &rec);
8721 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8722
8723 MsiViewClose(view);
8724 MsiCloseHandle(view);
8725
8726 query = "DELETE FROM `T` WHERE `A` IS NULL";
8727 r = run_query(hdb, 0, query);
8728 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8729
8730 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8731 r = run_query(hdb, 0, query);
8732 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8733
8734 query = "SELECT * FROM `T`";
8735 r = MsiDatabaseOpenViewA(hdb, query, &view);
8736 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8737 r = MsiViewExecute(view, 0);
8738 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8739
8740 for (i = 0; i < 6; i++)
8741 {
8742 r = MsiViewFetch(view, &rec);
8743 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8744
8745 r = MsiRecordGetInteger(rec, 1);
8746 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8747
8748 r = MsiRecordGetInteger(rec, 2);
8749 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8750
8751 r = MsiRecordGetInteger(rec, 3);
8752 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8753
8754 MsiCloseHandle(rec);
8755 }
8756
8757 r = MsiViewFetch(view, &rec);
8758 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8759
8760 MsiViewClose(view);
8761 MsiCloseHandle(view);
8762 MsiCloseHandle(hdb);
8763 DeleteFileA(msifile);
8764 }
8765
8766 static void test_columnorder(void)
8767 {
8768 MSIHANDLE hdb, view, rec;
8769 char buf[MAX_PATH];
8770 LPCSTR query;
8771 DWORD sz;
8772 UINT r;
8773
8774 hdb = create_db();
8775 ok(hdb, "failed to create db\n");
8776
8777 /* Each column is a slot:
8778 * ---------------------
8779 * | B | C | A | E | D |
8780 * ---------------------
8781 *
8782 * When a column is selected as a primary key,
8783 * the column occupying the nth primary key slot is swapped
8784 * with the current position of the primary key in question:
8785 *
8786 * set primary key `D`
8787 * --------------------- ---------------------
8788 * | B | C | A | E | D | -> | D | C | A | E | B |
8789 * --------------------- ---------------------
8790 *
8791 * set primary key `E`
8792 * --------------------- ---------------------
8793 * | D | C | A | E | B | -> | D | E | A | C | B |
8794 * --------------------- ---------------------
8795 */
8796
8797 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8798 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8799 "PRIMARY KEY `D`, `E`)";
8800 r = run_query(hdb, 0, query);
8801 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8802
8803 query = "SELECT * FROM `T`";
8804 r = MsiDatabaseOpenViewA(hdb, query, &view);
8805 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8806
8807 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8808 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8809
8810 sz = MAX_PATH;
8811 lstrcpyA(buf, "kiwi");
8812 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8813 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8814 ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
8815
8816 sz = MAX_PATH;
8817 lstrcpyA(buf, "kiwi");
8818 r = MsiRecordGetStringA(rec, 2, buf, &sz);
8819 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8820 ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
8821
8822 sz = MAX_PATH;
8823 lstrcpyA(buf, "kiwi");
8824 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8825 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8826 ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
8827
8828 sz = MAX_PATH;
8829 lstrcpyA(buf, "kiwi");
8830 r = MsiRecordGetStringA(rec, 4, buf, &sz);
8831 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8832 ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8833
8834 sz = MAX_PATH;
8835 lstrcpyA(buf, "kiwi");
8836 r = MsiRecordGetStringA(rec, 5, buf, &sz);
8837 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8838 ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
8839
8840 MsiCloseHandle(rec);
8841
8842 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8844
8845 sz = MAX_PATH;
8846 lstrcpyA(buf, "kiwi");
8847 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8848 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8849 ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8850
8851 sz = MAX_PATH;
8852 lstrcpyA(buf, "kiwi");
8853 r = MsiRecordGetStringA(rec, 2, buf, &sz);
8854 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8855 ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8856
8857 sz = MAX_PATH;
8858 lstrcpyA(buf, "kiwi");
8859 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8860 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8861 ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8862
8863 sz = MAX_PATH;
8864 lstrcpyA(buf, "kiwi");
8865 r = MsiRecordGetStringA(rec, 4, buf, &sz);
8866 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8867 ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8868
8869 sz = MAX_PATH;
8870 lstrcpyA(buf, "kiwi");
8871 r = MsiRecordGetStringA(rec, 5, buf, &sz);
8872 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8873 ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
8874
8875 MsiCloseHandle(rec);
8876 MsiViewClose(view);
8877 MsiCloseHandle(view);
8878
8879 query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8880 "VALUES ( 1, 2, 'a', 3, 'bc' )";
8881 r = run_query(hdb, 0, query);
8882 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8883
8884 query = "SELECT * FROM `T`";
8885 r = do_query(hdb, query, &rec);
8886 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8887
8888 sz = MAX_PATH;
8889 lstrcpyA(buf, "kiwi");
8890 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8891 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8892 ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
8893
8894 r = MsiRecordGetInteger(rec, 2);
8895 ok(r == 3, "Expected 3, got %d\n", r);
8896
8897 sz = MAX_PATH;
8898 lstrcpyA(buf, "kiwi");
8899 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8900 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8901 ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
8902
8903 r = MsiRecordGetInteger(rec, 4);
8904 ok(r == 2, "Expected 2, got %d\n", r);
8905
8906 r = MsiRecordGetInteger(rec, 5);
8907 ok(r == 1, "Expected 1, got %d\n", r);
8908
8909 MsiCloseHandle(rec);
8910
8911 query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
8912 r = MsiDatabaseOpenViewA(hdb, query, &view);
8913 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8914 r = MsiViewExecute(view, 0);
8915 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8916
8917 r = MsiViewFetch(view, &rec);
8918 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8919
8920 sz = MAX_PATH;
8921 lstrcpyA(buf, "kiwi");
8922 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8923 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8924 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8925
8926 r = MsiRecordGetInteger(rec, 2);
8927 ok(r == 1, "Expected 1, got %d\n", r);
8928
8929 sz = MAX_PATH;
8930 lstrcpyA(buf, "kiwi");
8931 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8932 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8933 ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
8934
8935 MsiCloseHandle(rec);
8936
8937 r = MsiViewFetch(view, &rec);
8938 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8939
8940 sz = MAX_PATH;
8941 lstrcpyA(buf, "kiwi");
8942 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8943 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8944 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8945
8946 r = MsiRecordGetInteger(rec, 2);
8947 ok(r == 2, "Expected 2, got %d\n", r);
8948
8949 sz = MAX_PATH;
8950 lstrcpyA(buf, "kiwi");
8951 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8952 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8953 ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
8954
8955 MsiCloseHandle(rec);
8956
8957 r = MsiViewFetch(view, &rec);
8958 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8959
8960 sz = MAX_PATH;
8961 lstrcpyA(buf, "kiwi");
8962 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8963 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8964 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8965
8966 r = MsiRecordGetInteger(rec, 2);
8967 ok(r == 3, "Expected 3, got %d\n", r);
8968
8969 sz = MAX_PATH;
8970 lstrcpyA(buf, "kiwi");
8971 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8972 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8973 ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
8974
8975 MsiCloseHandle(rec);
8976
8977 r = MsiViewFetch(view, &rec);
8978 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8979
8980 sz = MAX_PATH;
8981 lstrcpyA(buf, "kiwi");
8982 r = MsiRecordGetStringA(rec, 1, buf, &sz);
8983 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8984 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
8985
8986 r = MsiRecordGetInteger(rec, 2);
8987 ok(r == 4, "Expected 4, got %d\n", r);
8988
8989 sz = MAX_PATH;
8990 lstrcpyA(buf, "kiwi");
8991 r = MsiRecordGetStringA(rec, 3, buf, &sz);
8992 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8993 ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
8994
8995 MsiCloseHandle(rec);
8996
8997 r = MsiViewFetch(view, &rec);
8998 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8999
9000 sz = MAX_PATH;
9001 lstrcpyA(buf, "kiwi");
9002 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9003 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9004 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9005
9006 r = MsiRecordGetInteger(rec, 2);
9007 ok(r == 5, "Expected 5, got %d\n", r);
9008
9009 sz = MAX_PATH;
9010 lstrcpyA(buf, "kiwi");
9011 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9012 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9013 ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9014
9015 MsiCloseHandle(rec);
9016
9017 r = MsiViewFetch(view, &rec);
9018 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9019
9020 MsiViewClose(view);
9021 MsiCloseHandle(view);
9022
9023 query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
9024 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
9025 "PRIMARY KEY `C`, `A`, `D`)";
9026 r = run_query(hdb, 0, query);
9027 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9028
9029 query = "SELECT * FROM `Z`";
9030 r = MsiDatabaseOpenViewA(hdb, query, &view);
9031 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9032
9033 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
9034 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9035
9036 sz = MAX_PATH;
9037 lstrcpyA(buf, "kiwi");
9038 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9039 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9040 ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9041
9042 sz = MAX_PATH;
9043 lstrcpyA(buf, "kiwi");
9044 r = MsiRecordGetStringA(rec, 2, buf, &sz);
9045 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9046 ok(!lstrcmpA("S255", buf), "Expected \"S255\", got \"%s\"\n", buf);
9047
9048 sz = MAX_PATH;
9049 lstrcpyA(buf, "kiwi");
9050 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9051 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9052 ok(!lstrcmpA("s255", buf), "Expected \"s255\", got \"%s\"\n", buf);
9053
9054 sz = MAX_PATH;
9055 lstrcpyA(buf, "kiwi");
9056 r = MsiRecordGetStringA(rec, 4, buf, &sz);
9057 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9058 ok(!lstrcmpA("I2", buf), "Expected \"I2\", got \"%s\"\n", buf);
9059
9060 sz = MAX_PATH;
9061 lstrcpyA(buf, "kiwi");
9062 r = MsiRecordGetStringA(rec, 5, buf, &sz);
9063 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9064 ok(!lstrcmpA("i2", buf), "Expected \"i2\", got \"%s\"\n", buf);
9065
9066 MsiCloseHandle(rec);
9067
9068 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
9069 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9070
9071 sz = MAX_PATH;
9072 lstrcpyA(buf, "kiwi");
9073 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9074 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9075 ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9076
9077 sz = MAX_PATH;
9078 lstrcpyA(buf, "kiwi");
9079 r = MsiRecordGetStringA(rec, 2, buf, &sz);
9080 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9081 ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9082
9083 sz = MAX_PATH;
9084 lstrcpyA(buf, "kiwi");
9085 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9086 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9087 ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9088
9089 sz = MAX_PATH;
9090 lstrcpyA(buf, "kiwi");
9091 r = MsiRecordGetStringA(rec, 4, buf, &sz);
9092 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9093 ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9094
9095 sz = MAX_PATH;
9096 lstrcpyA(buf, "kiwi");
9097 r = MsiRecordGetStringA(rec, 5, buf, &sz);
9098 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9099 ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9100
9101 MsiCloseHandle(rec);
9102 MsiViewClose(view);
9103 MsiCloseHandle(view);
9104
9105 query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
9106 "VALUES ( 1, 2, 'a', 3, 'bc' )";
9107 r = run_query(hdb, 0, query);
9108 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9109
9110 query = "SELECT * FROM `Z`";
9111 r = do_query(hdb, query, &rec);
9112 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9113
9114 r = MsiRecordGetInteger(rec, 1);
9115 ok(r == 2, "Expected 2, got %d\n", r);
9116
9117 sz = MAX_PATH;
9118 lstrcpyA(buf, "kiwi");
9119 r = MsiRecordGetStringA(rec, 2, buf, &sz);
9120 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9121 ok(!lstrcmpA("a", buf), "Expected \"a\", got \"%s\"\n", buf);
9122
9123 sz = MAX_PATH;
9124 lstrcpyA(buf, "kiwi");
9125 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9126 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9127 ok(!lstrcmpA("bc", buf), "Expected \"bc\", got \"%s\"\n", buf);
9128
9129 r = MsiRecordGetInteger(rec, 4);
9130 ok(r == 3, "Expected 3, got %d\n", r);
9131
9132 r = MsiRecordGetInteger(rec, 5);
9133 ok(r == 1, "Expected 1, got %d\n", r);
9134
9135 MsiCloseHandle(rec);
9136
9137 query = "SELECT * FROM `_Columns` WHERE `Table` = 'T'";
9138 r = MsiDatabaseOpenViewA(hdb, query, &view);
9139 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9140 r = MsiViewExecute(view, 0);
9141 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9142
9143 r = MsiViewFetch(view, &rec);
9144 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9145
9146 sz = MAX_PATH;
9147 lstrcpyA(buf, "kiwi");
9148 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9149 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9150 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9151
9152 r = MsiRecordGetInteger(rec, 2);
9153 ok(r == 1, "Expected 1, got %d\n", r);
9154
9155 sz = MAX_PATH;
9156 lstrcpyA(buf, "kiwi");
9157 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9158 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9159 ok(!lstrcmpA("D", buf), "Expected \"D\", got \"%s\"\n", buf);
9160
9161 MsiCloseHandle(rec);
9162
9163 r = MsiViewFetch(view, &rec);
9164 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9165
9166 sz = MAX_PATH;
9167 lstrcpyA(buf, "kiwi");
9168 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9169 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9170 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9171
9172 r = MsiRecordGetInteger(rec, 2);
9173 ok(r == 2, "Expected 2, got %d\n", r);
9174
9175 sz = MAX_PATH;
9176 lstrcpyA(buf, "kiwi");
9177 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9178 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9179 ok(!lstrcmpA("E", buf), "Expected \"E\", got \"%s\"\n", buf);
9180
9181 MsiCloseHandle(rec);
9182
9183 r = MsiViewFetch(view, &rec);
9184 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9185
9186 sz = MAX_PATH;
9187 lstrcpyA(buf, "kiwi");
9188 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9189 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9190 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9191
9192 r = MsiRecordGetInteger(rec, 2);
9193 ok(r == 3, "Expected 3, got %d\n", r);
9194
9195 sz = MAX_PATH;
9196 lstrcpyA(buf, "kiwi");
9197 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9199 ok(!lstrcmpA("A", buf), "Expected \"A\", got \"%s\"\n", buf);
9200
9201 MsiCloseHandle(rec);
9202
9203 r = MsiViewFetch(view, &rec);
9204 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9205
9206 sz = MAX_PATH;
9207 lstrcpyA(buf, "kiwi");
9208 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9209 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9210 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9211
9212 r = MsiRecordGetInteger(rec, 2);
9213 ok(r == 4, "Expected 4, got %d\n", r);
9214
9215 sz = MAX_PATH;
9216 lstrcpyA(buf, "kiwi");
9217 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9218 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9219 ok(!lstrcmpA("C", buf), "Expected \"C\", got \"%s\"\n", buf);
9220
9221 MsiCloseHandle(rec);
9222
9223 r = MsiViewFetch(view, &rec);
9224 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9225
9226 sz = MAX_PATH;
9227 lstrcpyA(buf, "kiwi");
9228 r = MsiRecordGetStringA(rec, 1, buf, &sz);
9229 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9230 ok(!lstrcmpA("T", buf), "Expected \"T\", got \"%s\"\n", buf);
9231
9232 r = MsiRecordGetInteger(rec, 2);
9233 ok(r == 5, "Expected 5, got %d\n", r);
9234
9235 sz = MAX_PATH;
9236 lstrcpyA(buf, "kiwi");
9237 r = MsiRecordGetStringA(rec, 3, buf, &sz);
9238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9239 ok(!lstrcmpA("B", buf), "Expected \"B\", got \"%s\"\n", buf);
9240
9241 MsiCloseHandle(rec);
9242
9243 r = MsiViewFetch(view, &rec);
9244 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9245
9246 MsiViewClose(view);
9247 MsiCloseHandle(view);
9248
9249 MsiCloseHandle(hdb);
9250 DeleteFileA(msifile);
9251 }
9252
9253 static void test_createtable(void)
9254 {
9255 MSIHANDLE hdb, htab = 0, hrec = 0;
9256 LPCSTR query;
9257 UINT res;
9258 DWORD size;
9259 char buffer[0x20];
9260
9261 hdb = create_db();
9262 ok(hdb, "failed to create db\n");
9263
9264 query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
9265 res = MsiDatabaseOpenViewA( hdb, query, &htab );
9266 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9267 if(res == ERROR_SUCCESS )
9268 {
9269 res = MsiViewExecute( htab, hrec );
9270 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9271
9272 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9273 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9274
9275 size = sizeof(buffer);
9276 res = MsiRecordGetStringA(hrec, 1, buffer, &size );
9277 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9278 MsiCloseHandle( hrec );
9279
9280 res = MsiViewClose( htab );
9281 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9282
9283 res = MsiCloseHandle( htab );
9284 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9285 }
9286
9287 query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
9288 res = MsiDatabaseOpenViewA( hdb, query, &htab );
9289 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9290 if(res == ERROR_SUCCESS )
9291 {
9292 res = MsiViewExecute( htab, 0 );
9293 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9294
9295 res = MsiViewClose( htab );
9296 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9297
9298 res = MsiCloseHandle( htab );
9299 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9300
9301 query = "SELECT * FROM `a`";
9302 res = MsiDatabaseOpenViewA( hdb, query, &htab );
9303 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9304
9305 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9306 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9307
9308 buffer[0] = 0;
9309 size = sizeof(buffer);
9310 res = MsiRecordGetStringA(hrec, 1, buffer, &size );
9311 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9312 ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9313 MsiCloseHandle( hrec );
9314
9315 res = MsiViewClose( htab );
9316 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9317
9318 res = MsiCloseHandle( htab );
9319 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9320
9321 res = MsiDatabaseCommit(hdb);
9322 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9323
9324 res = MsiCloseHandle(hdb);
9325 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9326
9327 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
9328 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9329
9330 query = "SELECT * FROM `a`";
9331 res = MsiDatabaseOpenViewA( hdb, query, &htab );
9332 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9333
9334 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
9335 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9336
9337 buffer[0] = 0;
9338 size = sizeof(buffer);
9339 res = MsiRecordGetStringA(hrec, 1, buffer, &size );
9340 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9341 ok(!strcmp(buffer,"b"), "b != %s\n", buffer);
9342
9343 res = MsiCloseHandle( hrec );
9344 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9345
9346 res = MsiViewClose( htab );
9347 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9348
9349 res = MsiCloseHandle( htab );
9350 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9351 }
9352
9353 res = MsiDatabaseCommit(hdb);
9354 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9355
9356 res = MsiCloseHandle(hdb);
9357 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
9358
9359 DeleteFileA(msifile);
9360 }
9361
9362 static void test_embedded_nulls(void)
9363 {
9364 static const char control_table[] =
9365 "Dialog\tText\n"
9366 "s72\tL0\n"
9367 "Control\tDialog\n"
9368 "LicenseAgreementDlg\ttext\x11\x19text\0text";
9369 UINT r, sz;
9370 MSIHANDLE hdb, hrec;
9371 char buffer[32];
9372
9373 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
9374 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
9375
9376 GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
9377 write_file( "temp_file", control_table, sizeof(control_table) );
9378 r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
9379 ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
9380 DeleteFileA( "temp_file" );
9381
9382 r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
9383 ok( r == ERROR_SUCCESS, "query failed %u\n", r );
9384
9385 buffer[0] = 0;
9386 sz = sizeof(buffer);
9387 r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
9388 ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
9389 ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
9390
9391 MsiCloseHandle( hrec );
9392 MsiCloseHandle( hdb );
9393 DeleteFileA( msifile );
9394 }
9395
9396 static void test_select_column_names(void)
9397 {
9398 MSIHANDLE hdb = 0, rec, rec2, view;
9399 char buffer[32];
9400 UINT r, size;
9401
9402 DeleteFileA(msifile);
9403
9404 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
9405 ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r );
9406
9407 r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)");
9408 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9409
9410 r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" );
9411 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9412
9413 r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9414 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9415
9416 r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9417 todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
9418
9419 r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
9420 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9421
9422 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" );
9423 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9424
9425 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" );
9426 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9427
9428 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" );
9429 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9430
9431 r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" );
9432 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9433
9434 r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" );
9435 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9436
9437 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" );
9438 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9439
9440 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" );
9441 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9442
9443 r = MsiDatabaseOpenViewA( hdb, "SELECT '' FROM `t`", &view );
9444 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9445
9446 r = MsiViewExecute( view, 0 );
9447 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9448
9449 r = MsiViewFetch( view, &rec );
9450 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9451 r = MsiRecordGetFieldCount( rec );
9452 ok( r == 1, "got %u\n", r );
9453 r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec2 );
9454 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9455 r = MsiRecordGetFieldCount( rec2 );
9456 ok( r == 1, "got %u\n", r );
9457 size = sizeof(buffer);
9458 memset( buffer, 0x55, sizeof(buffer) );
9459 r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9460 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9461 ok( !buffer[0], "got \"%s\"\n", buffer );
9462 MsiCloseHandle( rec2 );
9463 r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec2 );
9464 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9465 r = MsiRecordGetFieldCount( rec2 );
9466 ok( r == 1, "got %u\n", r );
9467 size = sizeof(buffer);
9468 memset( buffer, 0x55, sizeof(buffer) );
9469 r = MsiRecordGetStringA( rec2, 1, buffer, &size );
9470 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9471 ok( !lstrcmpA( buffer, "f0" ), "got \"%s\"\n", buffer );
9472 MsiCloseHandle( rec2 );
9473
9474 size = sizeof(buffer);
9475 memset( buffer, 0x55, sizeof(buffer) );
9476 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9477 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9478 ok( !buffer[0], "got \"%s\"\n", buffer );
9479 MsiCloseHandle( rec );
9480
9481 r = MsiViewFetch( view, &rec );
9482 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9483 size = sizeof(buffer);
9484 memset( buffer, 0x55, sizeof(buffer) );
9485 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9486 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9487 ok( !buffer[0], "got \"%s\"\n", buffer );
9488 MsiCloseHandle( rec );
9489
9490 r = MsiViewFetch( view, &rec );
9491 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9492 MsiCloseHandle( rec );
9493
9494 MsiViewClose( view );
9495 MsiCloseHandle( view );
9496
9497 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '' FROM `t`", &view );
9498 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9499
9500 r = MsiViewExecute( view, 0 );
9501 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9502
9503 r = MsiViewFetch( view, &rec );
9504 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9505 r = MsiRecordGetFieldCount( rec );
9506 ok( r == 2, "got %u\n", r );
9507 size = sizeof(buffer);
9508 memset( buffer, 0x55, sizeof(buffer) );
9509 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9510 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9511 ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9512 MsiCloseHandle( rec );
9513
9514 r = MsiViewFetch( view, &rec );
9515 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9516 size = sizeof(buffer);
9517 memset( buffer, 0x55, sizeof(buffer) );
9518 r = MsiRecordGetStringA( rec, 2, buffer, &size );
9519 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9520 ok( !buffer[0], "got \"%s\"\n", buffer );
9521 MsiCloseHandle( rec );
9522
9523 r = MsiViewFetch( view, &rec );
9524 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9525 MsiCloseHandle( rec );
9526
9527 MsiViewClose( view );
9528 MsiCloseHandle( view );
9529
9530 r = MsiDatabaseOpenViewA( hdb, "SELECT '', `a` FROM `t`", &view );
9531 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9532
9533 r = MsiViewExecute( view, 0 );
9534 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9535
9536 r = MsiViewFetch( view, &rec );
9537 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9538 r = MsiRecordGetFieldCount( rec );
9539 ok( r == 2, "got %u\n", r );
9540 size = sizeof(buffer);
9541 memset( buffer, 0x55, sizeof(buffer) );
9542 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9543 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9544 ok( !buffer[0], "got \"%s\"\n", buffer );
9545 size = sizeof(buffer);
9546 memset( buffer, 0x55, sizeof(buffer) );
9547 r = MsiRecordGetStringA( rec, 2, buffer, &size );
9548 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9549 ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9550 MsiCloseHandle( rec );
9551
9552 r = MsiViewFetch( view, &rec );
9553 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9554 size = sizeof(buffer);
9555 memset( buffer, 0x55, sizeof(buffer) );
9556 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9557 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9558 ok( !buffer[0], "got \"%s\"\n", buffer );
9559 size = sizeof(buffer);
9560 memset( buffer, 0x55, sizeof(buffer) );
9561 r = MsiRecordGetStringA( rec, 2, buffer, &size );
9562 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9563 ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9564 MsiCloseHandle( rec );
9565
9566 r = MsiViewFetch( view, &rec );
9567 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9568 MsiCloseHandle( rec );
9569
9570 MsiViewClose( view );
9571 MsiCloseHandle( view );
9572
9573 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '', `b` FROM `t`", &view );
9574 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
9575
9576 r = MsiViewExecute( view, 0 );
9577 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
9578
9579 r = MsiViewFetch( view, &rec );
9580 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9581 r = MsiRecordGetFieldCount( rec );
9582 ok( r == 3, "got %u\n", r );
9583 size = sizeof(buffer);
9584 memset( buffer, 0x55, sizeof(buffer) );
9585 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9586 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9587 ok( !lstrcmpA( buffer, "1" ), "got \"%s\"\n", buffer );
9588 size = sizeof(buffer);
9589 memset( buffer, 0x55, sizeof(buffer) );
9590 r = MsiRecordGetStringA( rec, 2, buffer, &size );
9591 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9592 ok( !buffer[0], "got \"%s\"\n", buffer );
9593 size = sizeof(buffer);
9594 memset( buffer, 0x55, sizeof(buffer) );
9595 r = MsiRecordGetStringA( rec, 3, buffer, &size );
9596 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9597 ok( !lstrcmpA( buffer, "2" ), "got \"%s\"\n", buffer );
9598 MsiCloseHandle( rec );
9599
9600 r = MsiViewFetch( view, &rec );
9601 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9602 size = sizeof(buffer);
9603 memset( buffer, 0x55, sizeof(buffer) );
9604 r = MsiRecordGetStringA( rec, 1, buffer, &size );
9605 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9606 ok( !lstrcmpA( buffer, "3" ), "got \"%s\"\n", buffer );
9607 size = sizeof(buffer);
9608 memset( buffer, 0x55, sizeof(buffer) );
9609 r = MsiRecordGetStringA( rec, 2, buffer, &size );
9610 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9611 ok( !buffer[0], "got \"%s\"\n", buffer );
9612 size = sizeof(buffer);
9613 memset( buffer, 0x55, sizeof(buffer) );
9614 r = MsiRecordGetStringA( rec, 3, buffer, &size );
9615 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
9616 ok( !lstrcmpA( buffer, "4" ), "got \"%s\"\n", buffer );
9617 MsiCloseHandle( rec );
9618
9619 r = MsiViewFetch( view, &rec );
9620 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
9621 MsiCloseHandle( rec );
9622
9623 MsiViewClose( view );
9624 MsiCloseHandle( view );
9625
9626 r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" );
9627 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
9628
9629 r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" );
9630 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9631
9632 r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" );
9633 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9634
9635 r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" );
9636 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9637
9638 r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" );
9639 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
9640
9641 r = MsiCloseHandle( hdb );
9642 ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r);
9643 }
9644
9645 START_TEST(db)
9646 {
9647 test_msidatabase();
9648 test_msiinsert();
9649 test_msidecomposedesc();
9650 test_msibadqueries();
9651 test_viewmodify();
9652 test_viewgetcolumninfo();
9653 test_getcolinfo();
9654 test_msiexport();
9655 test_longstrings();
9656 test_streamtable();
9657 test_binary();
9658 test_where_not_in_selected();
9659 test_where();
9660 test_msiimport();
9661 test_binary_import();
9662 test_markers();
9663 test_handle_limit();
9664 test_try_transform();
9665 test_join();
9666 test_temporary_table();
9667 test_alter();
9668 test_integers();
9669 test_update();
9670 test_special_tables();
9671 test_tables_order();
9672 test_rows_order();
9673 test_select_markers();
9674 test_viewmodify_update();
9675 test_viewmodify_assign();
9676 test_stringtable();
9677 test_viewmodify_delete();
9678 test_defaultdatabase();
9679 test_order();
9680 test_viewmodify_delete_temporary();
9681 test_deleterow();
9682 test_quotes();
9683 test_carriagereturn();
9684 test_noquotes();
9685 test_forcecodepage();
9686 test_viewmodify_refresh();
9687 test_where_viewmodify();
9688 test_storages_table();
9689 test_dbtopackage();
9690 test_droptable();
9691 test_dbmerge();
9692 test_select_with_tablenames();
9693 test_insertorder();
9694 test_columnorder();
9695 test_suminfo_import();
9696 test_createtable();
9697 test_collation();
9698 test_embedded_nulls();
9699 test_select_column_names();
9700 }